问:
GPS + IMU data and kinematics equations
I have the following data

Longitudinal acceleration, $a_x^{IMU}$

Lateral acceleration, $a_y^{IMU}$

Vertical acceleration, $a_z^{IMU}$

Yaw angle, $\psi$

Yaw rate, $\dot{\psi}$

Latitude, $\rightarrow  Y$ ( UTM)

Longitude, $\rightarrow  X$ ( UTM)

Speed, $v$

Sampled from an IMU+GPS installed in a car at $10Hz$.

I want to define the motion equations in order to use a Kalman filter.

I've read this post, assuming $a_y=0$ (and $\dot{\psi} = 0)$, I was able to use the filter using these equations
$$
    \begin{cases}
      s_{x, t+1} = s_{x,t} + v_{t} \cos(\psi) \, dt + \frac{1}{2} a_{x, t}^{IMU} \cos(\psi) (dt)^2\\
      s_{y, t+1} = s_{y,t} + v_{t} \sin(\psi) \, dt + \frac{1}{2} a_{x, t}^{IMU} \sin(\psi) (dt)^2\\
      v_{t+1} = v_{t} + a_{x, t}^{IMU} \, dt \\
      a_{x, t+1} = a_{x, t}^{IMU}
    \end{cases}
$$
where $(s_x, s_y)$ are observed though $(X, Y)$.

How can I generalize the previous equations with $a_y^{IMU} \ne 0$? Moreover, how can I involve the yaw rate?

From Wikipedia the acceleration of a material point is given by
$$
\vec{a} = \frac{dv}{dt}\hat{u}_t + \frac{v^2}{R}\hat{u}_n.
$$

Am I right to assume
$$
\frac{dv}{dt} = a_x^{IMU}
$$
and
$$
\frac{v^2}{R} = \dot{\psi} \, v =  a_y^{IMU} \  \text{?}
$$

In particular, from Performance Vehicle Dynamics the lateral acceleration is given by the sum of two components
$$
a_Y = V \dot{\psi} + \dot{V_Y}
$$
Why the $a_Y$ above is the sum of two terms? $V \dot{\psi}$ and  $\dot{V_Y}$ (contrary to the acceleration of a material point equation)? How this equation is related to the $a_y^{IMU}$ data?

Thanks in advance!

答:
Why the $a_Y$ above is the sum of two terms?

From the article:

However, the car also has a horizontal side-slip velocity

The vehicle "lateral" vector $Y$ points perpendicular to the body frame, and thus the direction of travel and accel could be a combination of the forward and lateral velocities. The car is experiencing both "centripetal" accel to make it turn, and may be experiencing lateral accel as it slides perpendicularly.

Ynlike a point mass, which always travels "forward" and accelerates "sideways" and "forwards".

These [two] components are called the tangential acceleration and the normal or radial acceleration

To update when $a_y\neq 0$, you need to update all four of those equations to include a lateral velocity and accel. It will look almost like your accel and vel terms, but will be perpandicular (instead of $cos$ and $-sin$, you have $-cos$ and $sin$ as a unit vector).

And, you'll want to take a close look at $x$ and $y$ in your state equations. It appears from the third / fourth equation that $x$ is body fixed, whereas from the first two $x$ and $y$ are synonymous with Lat/Lon (e.g., earth fixed).

That's fine if $v$ is actually speed, which it is for a forward-accel-only vehicle, but with lateral accel, $v$ needs to be a vector of two velocities. After breaking apart velocity $(v_x(t), v_y(t))$ and accel $(a_x(t), a_y(t))$ and deciding on a common $x$ and $y$ for all equations, it will be easier to rewrite those state transition equations.

Title: GPS + IMU data and kinematics equations


问:
Quadcopter PID tuning
In continuation of the question I asked here: Quadcopter instability with simple takeoff in autonomous mode
  ...I'd like to ask a few questions about implementing a basic PID for a quadrotor controlled by an APM 2.6 module. (I'm using a frame from 3DRobotics)

I've stripped down the entire control system to just two PID blocks, one for controlling roll and another for controlling pitch (yaw and everything else... I'd think about them later).

I'm testing this setup on a rig which consists of a freely rotating beam, wherein I've tied down two of the arms of the quadrotor. The other two are free to move. So, I'm actually testing one degree of freedom (roll or pitch) at a time.

Check the image below: here A, B marks the freely rotating beam on which the setup is mounted.

With careful tuning of P and D parameters, I've managed to attain a sustained flight of about 30 seconds.

But by 'sustained', I simple mean a test where the drone ain't toppling over to one side. Rock steady flight is still no where in sight, and more than 30 secs of flight also looks quite difficult. It wobbles from the beginning. By the time it reaches 20 - 25 seconds, it starts tilting to one side. Within 30 secs, it has tilted to one side by an unacceptable margin. Soon enough, I find it resting upside down

As for the PID code itself, I'm calculating the proportional error from a 'complimentary filter' of gyro + accelerometer data. The integral term is set to zero. The P term comes to about 0.39 and the D term is at 0.0012. (I'm not using the Arduino PID library on purpose, just want to get one of my own PIDs implemented here.)

Check this video, if you want to see how it works.

http://www.youtube.com/watch?v=LpsNBL8ydBA&feature=youtu.be
[Yeh, the setup is pretty ancient! I agree. :)]

Please let me know what could I possibly do to improve stability at this stage.

@Ian: Of the many tests I did with my setup, I did plot graphs for some of the tests using the reading from the serial monitor. Here is a sample reading of Roll vs 'Motor1 & Motor2 - PWM input' (the two motors controlling the roll):

As for the input/output:

Input: Roll and pitch values (in degrees), as obtained by a combination of accelerometer + gyro

Output: PWM values for the motors, delivered using the Servo library's motor.write() function

Resolution

I resolved the problem. Here's how:

The crux of the issue lied in the way I implemented the Arduino program. I was using the write() function to update the servo angles, which happens to accept only integer steps in the argument (or somehow responds only to integer input, 100 and 100.2 produces the same result). I changed it to writeMicroseconds() and that made the copter considerably steadier.

I was adding up RPM on one motor while keeping the other at a steady value. I changed this to increase RPM in one motor while decreasing the opposing motor. That kinda keeps the total horizontal thrust unchanged, which might help me when I'm trying to get vertical altitude hold on this thing.

I was pushing up the RPM to the max limit, which is why the quadcopter kept losing control at full throttle. There was no room for the RPM to increase when it sensed a tilt.

I observed that one of the motor was inherently weaker than the other one, I do not know why. I hardcoded an offset into that motors PWM input.

Thanks for all the support.

Source Code:

If you're interested, here's the source code of my bare-bones PID implementation: PID Source Code

Please feel free to test it in your hardware. Any contributions to the project would be welcome.

答:
Well there could be a number of things going on here...

1) Are your reported angles correct? noisy? You can easily check that by manually tilting your quad and monitoring the values coming out.

2) your own PID implementation has a bug. You could use the trusted implementation out there to check your code.

3) Props, motors mounted the wrong way round.

4) ...

ContentLicense: CC BY-SA 3.0

Title: Quadcopter PID tuning


问:
Is there a way to turn the sound off of a Roomba?
I am working with an iRobot Create 2 and I work with others around me. Whenever I turn the robot on, send it an OI reset command, etc., it makes its various beeps and noises. I would like to not have this happen since I find it a little annoying and I'm sure those who have to work around me would like to have things quiet so they can concentrate on their work. Is there a way to accomplish turning off the beeps (while still being able to easily re-enable them), or am I out of luck?</p>

答:
Late late answer, but this is also the only thing that comes up when you Google this.
I ended up installing a 100 Ohm resistor on the speaker wire. It seems to be a good sweet spot for lowering the volume but still hearing it If you need to know it's location. 200 Ohm made it almost a whisper, for comparison.

I have a 690. I used this video https://youtu.be/s8K2gCzfTxE for taking it completely apart but stopped at the speaker.(don't Remove the circuit board)

The image shows the resistor before sealing it in shrink tubing.

As shown, you can also just disconnect the connector if you want to silence it, but not cut any wires.

ContentLicense: CC BY-SA 4.0


问:
Trying to get started with iRobot Create2 - need help reading sensors
I'm getting started helping high school students learn about robotics and we're trying to interface a Raspberry Pi 4 to the iRobot Create 2.  I've got them started with some sample code for moving the robot around, but haven't found much regarding how to read from the sensors and then use sensor data to drive robot actions.  We've been using the PyCreate2 library so far.

I'd definitely appreciate any help/guidance, examples that help us understand how to read sensor data (such as bumper sensors) and take action.

Thanks!
Bryan

答:
I suspect this is a question best answered by the author of the PyCreate2 library or by the manufacturer of the product, but here's a breadcrumb for you:

If you go to the library's GitHub repository, you will find an "examples" folder. There is a file there called "sensorExample.py" which has code for polling the sensors in a while loop. It doesn't act on them, but you could imagine modifying this example to get what you want. If you want to continue using this framework, I'd suggest polling the sensors in this loop and processing them in some kind of state machine in order to control the robot based on its current state and the sensor feedback.

Best of luck and happy hacking!

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


问:
Is this motion possible for this manipulator?
I'm currently solving the exercises of Modern Robotics book. I came across this problem but it is not clear to me how to approach it. I computed the analytic Jacobian which is

$$
\begin{bmatrix} \dot{x}\\\dot{y} \\ \dot{z}\end{bmatrix} =
\left(\begin{array}{ccc} L\,s_{\theta_1}\,s_{\theta_2}\,s_{\theta_3}-L\,c_{\theta_2}\,s_{\theta_1}-L\,c_{\theta_2}\,c_{\theta_3}\,s_{\theta_1}-L\,c_{\theta_1} & -L\,c_{\theta_1}\,\left(s_{\theta_2}+\sin\left(\theta_2+\theta_3\right)\right) & -L\,c_{\theta_1}\,\sin\left(\theta_2+\theta_3\right)\\ L\,c_{\theta_1}\,c_{\theta_2}-L\,s_{\theta_1}+L\,c_{\theta_1}\,c_{\theta_2}\,c_{\theta_3}-L\,c_{\theta_1}\,s_{\theta_2}\,s_{\theta_3} & -L\,s_{\theta_1}\,\left(s_{\theta_2}+\sin\left(\theta_2+\theta_3\right)\right) & -L\,s_{\theta_1}\,\sin\left(\theta_2+\theta_3\right)\\ 0 & L\,\left(c_{\theta_2}+\cos\left(\theta_2+\theta_3\right)\right) & L\,\cos\left(\theta_2+\theta_3\right) \end{array}\right)
\begin{bmatrix} \dot{\theta}_1\\\dot{\theta}_2 \\ \dot{\theta}_3\end{bmatrix}
$$
At zero configuration $\theta_1=\theta_2=\theta_3=0.$, we get
$$
\begin{bmatrix} \dot{x}\\\dot{y} \\ \dot{z}\end{bmatrix} =
\begin{bmatrix} -L&0&0\\2L&0&0\\0&2L&L\end{bmatrix}
\begin{bmatrix} \dot{\theta}_1\\\dot{\theta}_2 \\ \dot{\theta}_3\end{bmatrix}
$$
The analytic Jacobian is not invertible at this configuration. My conclusion is the motion is not possible but it seems to me according to the question, there is a possibility. Any suggestions?

答:
You are correct in determining that the motion is not possible, but you don't need to check if the matrix is invertible or not, you just need to solve the equation at the zero configuration.

If you plug in $[\dot x, \dot y, \dot z]^T = [10, 0, 0]^T$ to your equation at the zero configuration, you will find that to achieve the desired linear velocity you need to satisfy both $\theta_1 = -10/L$ and $\theta_1 = 0$. Therefore, it is not possible.


问:
Park and Lynch $F = ma$ derivation for a single rigid body
I'm having some conceptual difficulties with a derivation presented in the Modern Robotics text by Park and Lynch. Here are the relevant parts:

At the beginning of the book, they insist that ${\it all}$ frames used in the book are stationary, ${\it even}$ body-fixed frames. This has been extremely confusing for me, as we are constantly talking about body frames evolving in time, and there are many animations on the YouTube videos that depict embedded body-fixed frames that are ${\it not}$ stationary.

I assume they are trying to say that all body-fixed frames follow a sequence of stationary frames? Anyway...

My main confusion comes from the $[\omega_b] v_b$ term in their $F = m a$ statement. What is this term? Suppose a planar rigid body is simultaneously translating and rotating with, say, $v_b = [1,0,0]$ and $\omega_b = [0,0,1]$. The center of mass does not accelerate for this motion. Clearly $\dot{v}_b = 0$, but $[\omega_b]v_b = [0,1,0]$, so the equations tell me that a force must be present in the body y-direction to support this motion.

What am I missing?

EDIT:

Here is a possibility that makes sense to me. Suppose that the frame $\{{\bf b}_1, {\bf b}_2, {\bf b}_3\}$ is affixed to the body at its CG. Then, we can use this basis to describe the velocity of the CG of the body: $\bar{\bf v} = \bar{v}_i {\bf b}_i$. Now, the acceleration of the CG using this basis becomes $\bar{\bf a} = \dot{\bar{v}}_i {\bf b}_i + \boldsymbol{\omega} \times \bar{\bf v}$. Now if everything is represented on the $\{{\bf b}_i \}$ basis including the force ${\bf F} = F_i {\bf b}_i$ and angular velocity $\boldsymbol{\omega} = \omega_i {\bf b}_i$, then the matrix form of the three equations you get from ${\bf F} = m \bar{\bf a}$ becomes that obtained by the book.

This derivation is clean, but it assumes a $\textbf{non-inertial}$, $\textbf{non-stationary}$ frame $\{ {\bf b}_i \}$.

EDIT 2:
Here are the confusing remarks in question about stationary versus non-stationary frames:

EDIT 3: Interpretation of (8.22)

Consider a wheel rolling without slip to the right. Mark two neighboring points, $A$ and $B$.

These two material points follow their own flows through space, as in the perspective of system dynamics or fluid mechanics. Their paths look something like this:

Velocity profile of disk at any time looks something like this:

The interpretation of (8.22) is similar to the Eulerian description of fluid mechanics. If we choose the inertial point coincident with material point $A$, then at the next time instance, $B$ will occupy that point in space. Therefore, $\dot{v}_b$ is upwards, and clearly $[\omega_b] v_b$ is downwards. The two terms cancel to tell us at the current time instance that the acceleration of material point $A$ is zero, as expected.

答:
The key thing to remember is that none of the equations used in the Modern Robotics textbook use "body-fixed frames". The {b} frame is defined as a "body frame" which is instantaneously coincident (same position & orientation) with a body-fixed frame attached to the body (as stated in the grey box in your second edit).

This means that any body-fixed frame attached to any given body in a system can move as much as you want, but for every instant of time in which you need to formulate an equation, you will be using a fixed, inertial, instantaneous copy of the frame which the authors have (somewhat confusingly) labelled as the "body frame".

The second point that should be made is that the calculations you did in Edit 1 were for a stationary frame, not a rotating frame. Otherwise, you would have to also include one additional term in the velocity calculation and two additional terms in the acceleration calculation to deal with the rotating frame (see https://en.wikipedia.org/wiki/Centrifugal_force).


问:
Quadcopter instability with simple takeoff in autonomous mode
I'm trying to get a quad rotor to fly. The on board controller is an Ardupilot Mega 2.6, being programmed by Arduino 1.0.5.

I'm trying to fly it in simple autonomous mode, no Radio controller involved. I've done a thorough static weight balancing of the assembly (somewhat like this: http://www.youtube.com/watch?v=3nEvTeB2nX4) and the propellers are balanced correctly.

I'm trying to get the quadcopter to lift using this code:

```<code>#include <Servo.h>

int maxspeed = 155;
int minspeed = 0;

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

int val = 0;
int throttleCurveInitialGradient = 1;

void setup()
{

val = minspeed;

motor1.attach(7);
motor2.attach(8);
motor3.attach(11);
motor4.attach(12);

}

void loop()
{
setAllMotors(val);
delay(200);
val>maxspeed?true:val+=throttleCurveInitialGradient;
}

void setAllMotors(int val)
  {
    motor1.write(val);
    motor2.write(val);
    motor3.write(val);
    motor4.write(val);
  }
</code>```

But the issue is, as soon as the quadcopter takes off, it tilts heavily in one direction and topples over.

It looks like one of the motor/propeller is not generating enough thrust for that arm to take-off. I've even tried offsetting the weight balance against the direction that fails to lift, but it doesn't work (and I snapped a few propellers in the process);

Is there something wrong with the way the ESCs are being fired using
the Servo library?

If everything else fails, am I to assume there is something wrong
with the motors?

Do I need to implement a PID controller for self-balancing the roll
and pitch just to get this quadrotor to take off?

Edit 1:    Thanks for all the replies.

I got the PID in place. Actually, it is still a PD controller with the integral gain set to zero.

Here's how I'm writing the angles to the servo:

```<code>motor1.write((int)(val + (kP * pError1) +(kI * iError1) +(kD * dError1)));  //front left
motor2.write((int)(val + (kP * pError2) +(kI * iError2) +(kD * dError2)));  //rear right
motor3.write((int)(val + (kP * pError3) +(kI * iError3) +(kD * dError3)));  //front right
motor4.write((int)(val + (kP * pError4) +(kI * iError4) +(kD * dError4)));  //rear left
</code>```

kI is zero, so I'll ignore that.

With the value of kP set somewhere between 0.00051 to 0.00070, I'm getting an oscillation of steady amplitude around a supposed mean value. But the problem is, the amplitude of oscillation is way too high. It is somewhere around +/- 160 degrees, which looks crazy even on a tightly constrained test rig.

[  Edit 2: How I calculate the term 'pError' - Simple linear thresholding.

I've a precomputed data of the average readings (mean and SD) coming out of the gyro when the IMU is steady. Based on the gyro reading, I classify any motion of the setup as left, right, forward or backward.

For each of these motion, I increase the pError term for two of the motors, i.e, for right tilt, I add pError terms to motors 2 & 3, for left tilt, I add pError term to motors 1 & 4 etc. (check the comment lines in the code snippet given above).

The magnitude of error I assign to the pError term is = abs(current gyro reading) - abs(mean steady-state gyro reading). This value is always positive, therefore the side that is dipping downwards will always have a positive increment in RPM.  ]

As I crank up the derivative gain to around 0.0010 to 0.0015, the oscillation dampens rapidly and the drone comes to a relatively stable attitude hold, but not on the horizontal plane. The oscillation dies down (considerably, but not completely) only to give me a stable quadrotor tilted at 90 - 100 degrees with horizontal.

I'm using only the gyros for calculating the error. The gyros were self calibrated, hence I do expect a fair amount of noise and inaccuracy associated with the error values.

Do you think that is the primary reason for the high amplitude
oscillation?

One other probable reason might be the low update frequency of the errors. I'm updating the errors 6 times a second.

Could that be a probable reason it is taking longer to stabilise the
error?

And, for the steady state error after the wild oscillations dampen, is it necessary to fine tune the integral gain to get rid of that?

Please help.

Edit 3:  I cranked up the frequency of operation to 150+ Hz and what I get now is a very controlled oscillation (within +/- 10 degrees).

I'm yet to tune the derivative gain, following which I plan to recompute the errors for the integral gain using a combination of gyro and accelerometer data.

Edit 4:  I've tuned the P and D gain, resulting in +/- 5 degrees oscillation(approx). I can't get it to any lower than this, no matter how much I try.

There are two challenges about which I'm deeply concerned:

After 5 to 8 seconds of flight, the quadcopter is leaning into one side, albeit slowly.

A) Can this drift be controlled by tuning the integral gain?

B) Can the drift be controlled by using accelerometer + gyro fused data?

C) Given that my drone still shows +/- 5 degrees oscillation, can I consider this the optimal set point for the proportional and derivative gains? Or do I need to search more? (In which case, I'm really at my wits end here!)

答:
I can see several mistakes in your approach.

The biggest red flag for me is that you are treating the motors as individually-controlled PIDs when in fact they need to work in pairs.  I'm talking about this line that you posted:

```<code>motor1.write((int)(val + (kP * pError1) +(kI * iError1) +(kD * dError1)));  //front left
</code>```

The output of your PID should be the desired roll or pitch force -- the correction to the current pitch or roll vs what is desired.  The desired roll or pitch force will then be translated into the thrust ratio between the 2 motors that can effect that force.

The second problem I see is that you are using a PD controller instead of a PID controller and wondering why it appears to be imbalanced.  The integral term is precisely what you are missing -- it compensates for any (static) imbalance in the quadcopter itself.

The third (potential) problem that I see is that you might not be properly mapping the motor speed to the desired thrust -- that relationship may not be linear.

Body:
I can see several mistakes in your approach.

The biggest red flag for me is that you are treating the motors as individually-controlled PIDs when in fact they need to work in pairs.  I'm talking about this line that you posted:

motor1.write((int)(val + (kP * pError1) +(kI * iError1) +(kD * dError1)));  //front left

The output of your PID should be the desired roll or pitch force -- the correction to the current pitch or roll vs what is desired.  The desired roll or pitch force will then be translated into the thrust ratio between the 2 motors that can effect that force.

The second problem I see is that you are using a PD controller instead of a PID controller and wondering why it appears to be imbalanced.  The integral term is precisely what you are missing -- it compensates for any (static) imbalance in the quadcopter itself.

The third (potential) problem that I see is that you might not be properly mapping the motor speed to the desired thrust -- that relationship may not be linear.


问:
How to sync motor speeds when doing path planning for a robotic arm?
I am trying to sync the speeds of all motors in a 5 axis robotic arm.
By sync I mean determining the speed for each movement so that all axes finish their movement at the same time.

The problem I am having is calculating the max speed for each axis, given the motor speed limitations.

I am using a 5th degree polynom for path planning.

How to do suggest calculating the speed (time for the 5th degree polynom) for each movement?
Mabey using a 5th degree polynom is not the right approach, if so what is commonly used for path planning and speed syncing?

答:
You can use a fifth-degree (quintic) polynomial to describe motions for each axis. It is also possible to use other polynomials (second-degree, third-degree, etc.) but for polynomials with degrees lower than five, you will need a concatenation of polynomials (i.e. piecewise-polynomials) to describe motions of each axis.

Suppose the motions you are interested in starts and ends at rest (i.e. having zero velocity and acceleration). With this condition, you only need to calculate only one set of quintic coefficients $a, b, c, d, e, f$. Then the quintic cofficients for each of the axis will be just a scaled version of those coefficients.

To do this, let's suppose we have an extra, imaginary axis for this robot (just for this calculation) that moves from $0$ to $1$ and whose velocity limit $v_m$, acceleration limit $a_m$, and maybe jerk limit $j_m$ are determined by
$$
\begin{align}
v_m &= \min_{i} v_{m,i}/\text{displacement}_{i},\\
a_m &= \min_{i} a_{m,i}/\text{displacement}_{i},\\
j_m &= \min_{i} j_{m,i}/\text{displacement}_{i},
\end{align}
$$

where $\text{displacement}_{i}$ is how much axis $i$ moves, $v_{m,i}$ is the max velocity of axis $i$, and so on.

Now we are going to determine an appropriate quintic polynomial for this axis:
$$
p(t) = at^5 + bt^4 + ct^3 + dt^2 + et + f,
$$
which will describe a motion from time $t = 0$ to $t = T$, where $T$ is the total motion duration, which is still not determined at this point.

After we finish the calculation, we can then compute quintic coefficients for all "actual" robot axes just by scaling the above $a, b, \ldots, f$.

Given the boundary conditions (zero velocity and acceleration), we can compute the coefficients as follows
$$
a = \frac{6}{T^5}, b = \frac{-15}{T^4}, c = \frac{10}{T^3}, d = 0, e = 0, f = 0.
$$

So now we can actually view the polynomial equation as parameterized by two variables $p = p(t, T)$.

If there were no velocity/acceleration limits, etc. for the motor, we can assign $T$ arbitrarily. However, with the limits, we have to make sure that the computed polynomial is respecting the limit.

I'll just show here how to select $T$ based on the velocity limit $v_m$. Otherwise, it's going to be too long.

From the polynomial equation, the velocity profile can be computed as
$$
v(t, T) = \frac{d}{dt}p(t, T).
$$
This velocity profile has its peak at $t_p$, which solves the following equation
$$
\frac{d}{dt}v(t, T) = 0.
$$

Once we solve for $t_p$, we can then get the peak velocity as $v_p = v(t_p, T) = (15/8)/T$. So if we want the peak velocity to reach the maximum, then
$$
v_p = v_m = (15/8)T.
$$
Therefore, if we set $T = (15/8)/v_m$, we will have a quintic polynomial whose velocity profile reaches the max velocity. Call this duration $T_v$. In a similar fashion, we can compute, for example, $T_a$, which is the duration that make the velocity profile reaches max acceleration. Finally, select the duration as $T = \max(T_v, T_a, T_j)$.

Now that we have completely determine the quintic coefficients for this imaginary axis, we can obtain coefficients for axis $i$ from $a_i = a*\text{displacement}_i$, $b_i = b*\text{displacement}_i$, and so on.


问:
Forward kinematics confusing point
I am studying robot arm kinematics. In order to construct a transformation from a global coordinate frame to the end effector frame, I have seen references to the Denavit–Hartenberg (DH) convention. In this convention, a single operator is constructed for each joint which takes its frame to the next and depends on the angle of the joint and three other parameters specific to the convention.

However, in this paper, section 4.1.1 page 104 implies that the transformation chain can be deconstructed into two transformations for each joint, one of which represents the rotation about an arbitrary axis (the joint axis) and the other is a constant affine transformation.

Does anyone know how to deconstruct the chain as this paper references?  To me it seems that even what they call a constant affine transformation must still depend on the angle of the previous joint when compared to the DH method.

答:
The author of the referenced thesis is using exponential coordinates and screw theory via the Product of Exponentials formulation to generate the sequence of transformations from one link to the next.

They have separated out the constant offset from one joint to the next for a given link from the effects of each joint, but it is effectively using the same product of exponentials formulation which is explained very nicely in Chapter 4 of the Modern Robotics (MR) textbook by Lynch and Park (which is fully available online at http://modernrobotics.org, along with slides and videos explaining the key details).

To translate between the two formulations, the scalar thesis variable $j_i$ is the MR variable $\theta$, the vector $v_i$ is the MR vector $\hat \omega$, and the combined matrix product $T_iJ_i$ is the MR matrix $e^{[S]\theta}$, which combines both the constant transformation and the joint transformation via the screw axis $S$.

Title: Forward kinematics confusing point


问:
Difference between Denavit-Hartenberg and Rodrigues formulas/conventions
I am trying to compute the forward kinematics for a 6 DOF robot arm.

I've found two methods : the Denavit-Hartenberg (original and modified) and the product of exponentials with the Rodrigues formula.

But I did not found any paper on the advantages and disadvantages of these two.

This methods are very similar because we define the axis lengths and twist angles but how are they different?

Thanks a lot for your explanations.

答:
The DH method requires you to carefully specify local frames attached to each link and calculate linear and angular offsets between those frames in a very specific way in order to reduce the effective transformation from 6 variables down to 4. You then have to plug in your joint angle/positions and multiply the resulting transformation matrices to determine the end effector transformation (orientation & position). Computing the differential kinematics and dynamics using this formulation is challenging and can lead to numerical errors.

The Product of Exponentials formulation uses matrix exponentials for each joint and a transformation from the base to the end effector, all defined based on the zero-configuration (constants). The joint variables are then inserted into the exponentials to find the overall transformation resulting from the changes due to the joint motions. It makes the resulting differential kinematics and dynamics far easier and faster to compute.


问:
Is ADS-B receiver used in PixhawkCube ADS-B out or ADS-B In?
The new carrier boards for Pixhawk Cube seems to be using a 1090MHz ADS-B receiver from uAvionix. This receives location information from nearby aircraft (airplanes, gliders, helicopters, etc.), but will it also broadcast information to nearby vehicles as well or is it just a receiver?

I'm asking since there seems to be an ADS-B which sends and receives such information and is mandatory for aircrafts/quadcopters/helicopters/etc at specific airspace classes and not else where. It also seems there exists ADS-B out and ADS-B In, which I have no idea about their differences.

which of these two sensor is this one? is it only a receiver, or is it a full fledged ADS-B sensor?

答: It's a ADSB-In receiver. One can add a uAvionix ping200X, ping200XR, ping200SR, or ping20Si and all are transponders that respond to interrogation and also transmit ADSB Out.  https://uavionix.com/uas/</p>


问:
How to compute the Hessian matrix in the robustified Gauss-Newton method for optimization
When robustifying the Gauss-Newton method used to find a local minima of a squared error function expressed by:
$$f(\mathbf{x})=\frac{1}{2}\Delta\mathbf{z}(\mathbf{x})^T\Delta\mathbf{z}(\mathbf{x})$$,
as explained in works like Bundle adjustment: A Modern Synthesis (page 17), we have to introduce a strong nonlinearity into this cost function, which is denoted by $\rho(\cdot)$ (it can be e.g. the Huber loss).

Thereby to reduce the influence of outliers, we are no longer interested in minimizing $f(\mathbf{x})$, but the robustified version of it: $\rho(f(\mathbf{x}))$. Hence, the gradient vector ($\mathbf{g}$) and the approximate Hessian matrix ($\mathbf{H}$) are given by:

$$
\mathbf{g} = \rho'\mathbf{J}^T\Delta\mathbf{z},\quad\quad \mathbf{H} \approx \mathbf{J}^T(\rho'\,\mathbf{I} + 2\rho''\Delta\mathbf{z} (\Delta\mathbf{z})^T)\mathbf{J}
$$
Where $\rho'$ and $\rho''$ are the first and second derivatives of $\rho(f(\mathbf{x}))$ w.r.t $f(\mathbf{x})$. And $\mathbf{J}$ is the jacobian matrix given by: $\mathbf{J} = \partial \Delta\mathbf{z}/\partial \mathbf{x}$.

Given this, what I don't understand is how this approximation of the Hessian matrix is computed.

My attempt to reach it, is the following:
$$\begin{align}
\mathbf{H} &= \frac{\partial^2\rho(f(\mathbf{x}))}{\partial \mathbf{x}^2} = \frac{\partial\rho(f(\mathbf{x}))}{\partial f(\mathbf{x})}\frac{\partial^2 f(\mathbf{x})}{\partial \mathbf{x}^2} + \frac{\partial^2\rho(f(\mathbf{x}))}{\partial f(\mathbf{x})^2}\left(\frac{\partial f(\mathbf{x})}{\partial \mathbf{x}}\right)^2 && \text{By applying chain rule}
\end{align}
$$
Where:
$$\begin{align}
&\frac{\partial\rho(f(\mathbf{x}))}{\partial f(\mathbf{x})}\frac{\partial^2 f(\mathbf{x})}{\partial \mathbf{x}^2} \approx \rho'\mathbf{J}^T\mathbf{J}\quad\leftrightarrow\quad\text{Gauss-Newton approximation}\\
\\
&\frac{\partial^2\rho(f(\mathbf{x}))}{\partial f(\mathbf{x})^2}\left(\frac{\partial f(\mathbf{x})}{\partial \mathbf{x}}\right)^2 = \rho''\,\mathbf{J}^T\Delta\mathbf{z} (\Delta\mathbf{z})^T\mathbf{J}
\end{align}
$$
Thereby I am getting an approximated Hessian where the second term is not multplied by 2:
$$
\mathbf{H}_{\text{attempt}} \approx \mathbf{J}^T(\rho'\,\mathbf{I} + \rho''\Delta\mathbf{z} (\Delta\mathbf{z})^T)\mathbf{J} \neq \mathbf{J}^T(\rho'\,\mathbf{I} + \color{red}{2}\rho''\Delta\mathbf{z} (\Delta\mathbf{z})^T)\mathbf{J}
$$
Can please someone help me to see where I am doing the wrong step?

Thanks in advance!

答:
I was reading the same paper today. If you look at equation (3), the objective function is actually
$$\frac{1}{2}\rho(\mathbf{z}(\mathbf{x})^T \mathbf{z}(\mathbf{x})),$$
not what you stated at first
$$\rho(\frac{1}{2} \mathbf{z}(\mathbf{x})^T \mathbf{z}(\mathbf{x})).$$
Then $\left(\frac{\partial \mathbf{z}(\mathbf{x})^T \mathbf{z}(\mathbf{x})}{\partial \mathbf{x}}\right)^2$ will generate a coefficient $2^2=4$ at your second term.
So nothing in your derivation is wrong.


问:
Fusing non-continuous global pose data
I am fusing the map pose data which is calculated from the fiducial_slam node. Here the topic being fused with ekf_node is /fiducial_pose (geometry_msgs/PoseWithCovarianceStamped). The problem i'm getting is, once the fiducial_slam don't publishes the pose data when it don't detects any fiducial/aruco markers. The robot is continuously drifting namely the odom frame is drifting with respect to time even if the robot is not moving. Here is my ekf_node params:

```<code>    frequency: 10
    two_d_mode: true

    map_frame: map
    odom_frame: odom
    base_link_frame: base_footprint
    world_frame: map
    publish_tf: true

    transform_time_offset: 0.1

    smooth_lagged_data: true
    dynamic_process_noise_covariance: true

    odom0: base_controller/odom
    odom0_config: [false, false, false,
                   false, false, false,
               true,  false,  false,
               false, false, true,
               false, false, false]
# if odom0_differential is set to true x, y and yaw will be differentiated to get vx, vy and vyaw
odom0_differential: true

# Only use angular velocity from imu
imu0: /imu/data
imu0_config: [false, false, false,
              false, false, false,
              false,  false,  false,
              false, false, true,
              false, false, false]
imu0_differential: true
imu0_relative: true

# Use x,y position and yaw orientation data for map positioning
pose0: fiducial_pose
pose0_config: [true,  true,  false,
               false, false, true,
               false, false, false,
               false, false, false,
               false, false, false]

pose0_rejection_threshold: 2

# pose1: initialpose # External map position of robot
# pose1_config: [true,  true,  false,
#                false, false, true,
#                false, false, false,
#                false, false, false,
#                false, false, false]

# pose1_rejection_threshold: 3

# Since AMCL is more likely to fail than the beacons, you might want to treat the beacons
# as a primary source, and set pose1_differential: true
# In that case, set x', y' and yaw' to true, and the rest to false!

# pose1: /fiducial_pose # AMCL!
# pose1_config: [true,  true, false,
#                false, false, true,
#                false, false, false,
#                false, false, false,
#                false, false, false]

# pose1_rejection_threshold: 2

# poseN_rejection_threshold: (YOU MIGHT WANT THIS. If it's above the stated threshold value, the EKF will ignore the reading) (Defaults to numeric_limits<double>::max())

# [ADVANCED] The process noise covariance matrix can be difficult to tune, and can vary for each application, so it is exposed as a configuration parameter. This matrix represents the noise we add to the total error after each prediction step.

# The better the omnidirectional motion model matches your system, the smaller these values can be. However, if users find that a given variable is slow to converge, one approach is to increase the process_noise_covariance diagonal value for the variable in question, which will cause the filter's predicted error to be larger, which will cause the filter to trust the incoming measurement more during correction.

# The values are ordered as x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az.
# Defaults to the matrix below if unspecified.

###########################################################################################################################
###########################################################################################################################

process_noise_covariance: [0.05, 0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0.05, 0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0.06, 0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0.03, 0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0.03, 0,    0,     0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0.06, 0,     0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0.025, 0,     0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0.025, 0,    0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0.04, 0,    0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0,    0.01, 0,    0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0.01, 0,    0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0.02, 0,    0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0.01, 0,    0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0.01, 0,
                           0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0.015]

# This represents the initial value for the state estimate error covariance matrix. Setting a diagonal value (a

    # variance) to a large value will result in early measurements for that variable being accepted quickly. Users should
    # take care not to use large values for variables that will not be measured directly. The values are ordered as x, y,
    # z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az. Defaults to the matrix below if unspecified. -->
    initial_estimate_covariance: [1e-9, 0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    1e-9, 0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    1e-9, 0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    1e-9, 0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    1e-9, 0,    0,    0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    1e-9, 0,    0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    1e-9, 0,    0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    1e-9, 0,    0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    1e-9, 0,     0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    0,    1e-9,  0,     0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     1e-9,  0,     0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     1e-9,  0,    0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     1e-9, 0,    0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    1e-9, 0,
                                  0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    1e-9]
</code>```

Sample data of /base_controller/odom

```<code>header:
  seq: 648774
  stamp:
    secs: 21451
    nsecs: 299000000
  frame_id: "odom"
child_frame_id: "base_footprint"
pose:
  pose:
    position:
      x: 5.367360546622458
      y: -3.226477343717956
      z: 0.0
    orientation:
      x: 0.0
      y: 0.0
      z: -0.4181811120907099
      w: 0.9083636702833162
  covariance: [0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000.0]
twist:
  twist:
    linear:
      x: -7.84378820017917e-06
      y: 0.0
      z: 0.0
    angular:
      x: 0.0
      y: 0.0
      z: 0.00016012500416401316
  covariance: [0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1000.0]
</code>```

Sample data of /imu/data

```<code>header:
  seq: 355
  stamp:
    secs: 21481
    nsecs: 827000000
  frame_id: "imu_link"
orientation:
  x: -0.009432798620337163
  y: 0.0033289538551165613
  z: 0.005764668671223135
  w: 0.9999333522648045
orientation_covariance: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
angular_velocity:
  x: 1.5095815221125049e-05
  y: -5.4206682813852e-06
  z: 0.00032156750257625246
angular_velocity_covariance: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
linear_acceleration:
  x: 0.062312201562116566
  y: 0.1806256979113818
  z: -0.00469552164706144
linear_acceleration_covariance: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
</code>```

Sample data of /fiducial_pose

```<code>header:
  seq: 21
  stamp:
    secs: 21511
    nsecs: 510000000
  frame_id: "map"
pose:
  pose:
    position:
      x: 0.1341933242820686
      y: 0.8324998652571356
      z: -0.23602488517276732
    orientation:
      x: -0.011477776819870111
      y: -0.027899676141139317
      z: 0.26226075779434743
      w: 0.964525356655608
  covariance: [0.04663268945646209, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04663268945646209, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04663268945646209, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04663268945646209, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04663268945646209, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04663268945646209]
</code>```

Environment: OS: ubuntu 20.04 ROS version: noetic

答:
I can answer more definitively if you provide the information I requested in the comment above, but I can probably guess what's wrong anyway.

You have two_d_mode enabled, which means you need to provide references (measurements) for the following quantities:

X position or X velocity

Y position or Y velocity

Yaw or Yaw velocity

When you receive pose data from the fiducials, you are meeting all of the above criteria: you are fusing X position, X velocity, Y position, and Yaw velocity.

When your pose data is not published, you are missing the second bullet: you don't have any reference for Y or Y velocity. This means part of your state vector is not being measured, which will cause its error to explode. The correlation with other state variables means your state estimate will likely drift, sometimes wildly.

Fortunately, the answer here is simple: just set Y velocity to true in your odom0_config:

```<code>    odom0_config: [false, false, false,
                   false, false, false,
                   true,  true,  false,
                   false, false, true,
                   false, false, false]
</code>```

This assumes you have a nonholonomic (e.g., differential drive) base.

Title: Fusing non-continuous global pose data

Body:
I can answer more definitively if you provide the information I requested in the comment above, but I can probably guess what's wrong anyway.

You have two_d_mode enabled, which means you need to provide references (measurements) for the following quantities:

X position or X velocity

Y position or Y velocity

Yaw or Yaw velocity

When you receive pose data from the fiducials, you are meeting all of the above criteria: you are fusing X position, X velocity, Y position, and Yaw velocity.

When your pose data is not published, you are missing the second bullet: you don't have any reference for Y or Y velocity. This means part of your state vector is not being measured, which will cause its error to explode. The correlation with other state variables means your state estimate will likely drift, sometimes wildly.

Fortunately, the answer here is simple: just set Y velocity to true in your odom0_config:

    odom0_config: [false, false, false,
                   false, false, false,
                   true,  true,  false,
                   false, false, true,
                   false, false, false]

This assumes you have a nonholonomic (e.g., differential drive) base.


问:
Choosing a proper sampling time for a PID controller
I have a robotic system I'm controlling with Arduino, is there an heuristic way to determine a proper sampling time for my PID controller? Considering I have some other things to compute on my sketch that require time, but of course a good sampling time is crucial.

Basically I have a distance sensor that needs to detect at a constant rate an object that is moving, sometimes slow, sometimes fast. I don't have a good model of my system so I can't actually tell the physical frequency of the system.

答:
A simple rule of thump is based on the rise time that you want to achieve. This is basically the time that the final system needs to change form one position to another.

A reasonable choice is a value between 5 and 100 samples within the desired rise time.

The concrete choice may be influenced by a bunch of factors, for example:

Method of the controller design

available computing power

existing disturbances

For a little overview check my article https://www.imt.ch/en/insight/saving-computing-power-with-the-right-choice-of-sampling-time/

OwnerDisplayName: Gian Mauro Musso


问:
Why does the complexity of the particle filter scales exponentially with the number of dimentions?
In the AI for Robotics course from Udacity, Sebastian Thrun mentions that "the complexity of the particle filter grows exponentially with the number of dimensions". Why is this the case? We have to keep track of $n$ particles each of which has $d$ dimensions so wouldn't the memory complexity be $O(n*d)$?

答:
You need enough particles so that you can sample across each of those dimensions.

If I have a particle filter with just X position, and my particles are spread in the range [0, 1], I might need, e.g, 3 particles: {0, 0.5, 1.0}.

If I have a particle filter with (X, Y) position and both dimensions have  the same [0, 1] range, then I need one particle for every combination of X and Y: {(0, 0), (0, 0.5), (0, 1), (0.5, 0), (0.5, 0.5), (0.5, 1), (1, 0), (1, 0.5), (1, 1)}.


答: It's the number of particles that will grow exponentially. An array of particles, with $n$ particles in each dimension, with $d$ dimensions, will have $n^d$ particles.

Title: Why does the complexity of the particle filter scales exponentially with the number of dimentions?

Body: In the AI for Robotics course from Udacity, Sebastian Thrun mentions that "the complexity of the particle filter grows exponentially with the number of dimensions". Why is this the case? We have to keep track of $n$ particles each of which has $d$ dimensions so wouldn't the memory complexity be $O(n*d)$?


问:
Defining the specifications required by a 6DOF robot to impose a harmonic sinusoidal motion
Perhaps a bit of a simple question, but since I don't have a background in robotics/engineering, then I imagine this would be the perfect place to ask such a question.

I am buying a 6-DOF Stewart platform to perform an experiment. In this experiment, I will impose to the device (a small ship) that is attached to the platform (it will be something similar to the one on the picture attached) a harmonic motion over two degrees of freedom, in my case, it will be along the x-axis (surge) and along the y rotating axis (pitch). So that is, I want my device to go back and forth in a given frequency for a defined amplitude.

My question is: Given that I know the FREQUENCIES and the AMPLITUDES that I want to perform on my experiment as well as the WEIGHT of my ship. Then, how could I calculate the specifications needed to specify what would be required by the platform (in terms of forces and motion)?

答:
Let's assume that by "harmonic motion" you mean it can be modeled as sinusoidal. Then for a single coordinate $q$, the motion is $q = A \sin 2\pi f t$ where $A$ is the amplitude (let's use MKS units, so meters), $f$ is the frequency in Hertz (cycles per second), and $t$ is time (seconds). The velocity $v$ is $dq/dt$ and the acceleration $a$ is $d^2q/dt^2$. If I can still do derivatives in my head, $a = -A \sin 2\pi f t$.

The mass of your ship is its weight divided by $G$, measured in kg. Newton tells us that the force $F$ necessary to accelerate the mass is $F=ma$. That gives the instantaneous force that your device exerts on your ship.

To determine motor ratings, you would augment that with the additional forces to accelerate the setup itself, friction, mechanical (dis)advantage due to gearing or leverage, motor efficiency, thermal derating, and so on. Operating in two dimensions, they will interact because, for instance, pushing sideways on a bearing will increase the friction for the other dimension. All in all, that's why the question is open-ended.


问:
How would you sync a real life accelerometer with an accelerometer in a simulation program
How would you sync a real life accelerometer with an accelerometer in a simulation program.
In this case I am using MuJoCo for simulation and a Gy-521 is my physical, real life accelerometer.</p>

答:
Your question is very open ended as "syncing" is not clearly defined. I'm going to answer as best i can interpret your intent.

An accelerometer is a sensor which measures acceleration in the world. A simulated sensor in the simulation should likewise be measuring acceleration in the simulated world.

Do you that end to cause the simulated sensor to provide the same readings you should take the real sensors readings. Estimate the motions of the real system which caused those accelerations. Then send those motions to the simulator to be executed. And if you've estimated the motion accurately and modeled the system will enough in the simulation the accelerometers will be in sync, aka giving the same readings.


答:
It looks like your proportional gain is too high.

You seem to be constantly increasing RPM on one motor while locking in the other one to make the system rotate.  This isn't a good control strategy as eventually those are going to both saturate and you will lose control.  Also as time increases your ability to command the system decreases.  So you need a better model of the system.

If you deal with #1, and #2 you'll have a more stable system but you may not be happy with the control bandwidth.  To deal with that you need to make your system stiffer which includes getting rid of any lag on the sensor side of things and on the control side of things.

Title: Quadcopter PID tuning

Body:
In continuation of the question I asked here: Quadcopter instability with simple takeoff in autonomous mode
  ...I'd like to ask a few questions about implementing a basic PID for a quadrotor controlled by an APM 2.6 module. (I'm using a frame from 3DRobotics)

I've stripped down the entire control system to just two PID blocks, one for controlling roll and another for controlling pitch (yaw and everything else... I'd think about them later).

I'm testing this setup on a rig which consists of a freely rotating beam, wherein I've tied down two of the arms of the quadrotor. The other two are free to move. So, I'm actually testing one degree of freedom (roll or pitch) at a time.

Check the image below: here A, B marks the freely rotating beam on which the setup is mounted.

With careful tuning of P and D parameters, I've managed to attain a sustained flight of about 30 seconds.

But by 'sustained', I simple mean a test where the drone ain't toppling over to one side. Rock steady flight is still no where in sight, and more than 30 secs of flight also looks quite difficult. It wobbles from the beginning. By the time it reaches 20 - 25 seconds, it starts tilting to one side. Within 30 secs, it has tilted to one side by an unacceptable margin. Soon enough, I find it resting upside down

As for the PID code itself, I'm calculating the proportional error from a 'complimentary filter' of gyro + accelerometer data. The integral term is set to zero. The P term comes to about 0.39 and the D term is at 0.0012. (I'm not using the Arduino PID library on purpose, just want to get one of my own PIDs implemented here.)

Check this video, if you want to see how it works.

http://www.youtube.com/watch?v=LpsNBL8ydBA&feature=youtu.be
[Yeh, the setup is pretty ancient! I agree. :)]

Please let me know what could I possibly do to improve stability at this stage.

@Ian: Of the many tests I did with my setup, I did plot graphs for some of the tests using the reading from the serial monitor. Here is a sample reading of Roll vs 'Motor1 & Motor2 - PWM input' (the two motors controlling the roll):

As for the input/output:

Input: Roll and pitch values (in degrees), as obtained by a combination of accelerometer + gyro

Output: PWM values for the motors, delivered using the Servo library's motor.write() function

Resolution

I resolved the problem. Here's how:

The crux of the issue lied in the way I implemented the Arduino program. I was using the write() function to update the servo angles, which happens to accept only integer steps in the argument (or somehow responds only to integer input, 100 and 100.2 produces the same result). I changed it to writeMicroseconds() and that made the copter considerably steadier.

I was adding up RPM on one motor while keeping the other at a steady value. I changed this to increase RPM in one motor while decreasing the opposing motor. That kinda keeps the total horizontal thrust unchanged, which might help me when I'm trying to get vertical altitude hold on this thing.

I was pushing up the RPM to the max limit, which is why the quadcopter kept losing control at full throttle. There was no room for the RPM to increase when it sensed a tilt.

I observed that one of the motor was inherently weaker than the other one, I do not know why. I hardcoded an offset into that motors PWM input.

Thanks for all the support.

Source Code:

If you're interested, here's the source code of my bare-bones PID implementation: PID Source Code

Please feel free to test it in your hardware. Any contributions to the project would be welcome.


问:
Merging multiple LIDARs real time
Is there a standard practice for merging the pointclouds generated by several LIDARs when there is overlap?

For example, if my vehicle has two LIDARS (front and back) I'd rather fuse and deal with a single pointcloud in the perception pipeline than two. Each LIDAR pointcloud will definitely have unique sections in their FOV, but there will definitely also be overlap. The vehicle geometry can make this overlap not geometrically simple.

Is the standard practice just to add them on top of one another? What should one then do about overlap? Perhaps just accept it and move on? I think things like ICP and the like are out of the question since the interest is to have one pointcloud per time sample to use for the perception pipeline, the interest here is not for mapping.

答:
Certainly merging two laser scans into a single point cloud is doable. Here's an example tool and you can easily concatenate said point clouds too.

However I'd like to suggest that you reconsider some of your assumptions in your question.

Each LIDAR pointcloud will definitely have unique sections in their FOV, but there will definitely also be overlap.

Do they really overlap? Aka they point to the same point exactly, or do they overlap only if you're assuming that they are planar. And also if they see the same object from different angles does that give you more information? Are they vertically alligned and planar? Do they have different viewing angles, different heights.

I think things like ICP and the like are out of the question since the interest is to have one pointcloud per time sample to use for the perception pipeline, the interest here is not for mapping.

ICP can be applied to any sequence of point clouds. There's no rule about when or how to update. Many implementations may be optimized for taking repeated scans from the same scanning laser sensor as that's the most common use case.

A fused cloud may be better for doing things like general obstacle avoidance.
Using each scan individually for sequential ICP may be the best way to track odometry. Some algorithms can take advantage of the semantic meaning of getting one consistent laser scan, while some can benefit from having a less structured fused data source. And others may actually want the multiple feeds fed in in the raw format and they will do their own fusion.

With that said I would suggest that both it's not an either/or question but what will serve your application best. You may want to do both feeding different forms of the data to different algorithms to enable them to operate optimally.

Is the standard practice just to add them on top of one another? What should one then do about overlap?

It completely depends on how you plan to use the data. There's a whole field of study called sensor fusion which I would recommend you do some reading on and ask more specific questions when if you have them. This is too large a scope to answer here.

Title: Merging multiple LIDARs real time


问:
As long as features are same does MCU Case Style make a difference?
I recently got into the field of Microcontrollers and it is my first time buying a custom one (other than arduinos and rasp pis) and I noticed these 2 on the shopping pages…

My question is that since both of these have only MCU Case Style difference feature-wise, is there any difference in the actual thing other than the case style, (life, interoperability, tips etc.). Also is a difference in the case style gonna make it hard for me to use it on an average breadboard? Do you have any tips for which one should be preferred and if not any major difference should I just go for the cheaper one since there isn’t much difference anyways??

https://in.element14.com/w/c/semiconductors-ics/microcontrollers-mcu/16-32-bit-microcontrollers-mcu-avr/prl/results?ost=microcontroller&sort=P_PRICE

答:
Notice the Microchip specifications for either of the pictured processors is the same document on the vendors web page.  On the second page there is a breakdown on the processor numbering scheme:

... the only difference between the two selected processors are the last to characters.  SS and SO.  From the above image we see this is used to specify either SSOP or SOIC packaging.  Neither will plug in to most 1/10 inch spaced breadboards with out an adapter.

Here is an image of a TSSOP to 1/10 inch bread board adapter:

... likely you can use such a PCB to convert the processor ending in SO so that it can be used on a 1/10 inch bread board.


问:
Is it practical to 3D print a refractive lens?
A lot of awesome optics projects like hacking cameras and projectors become possible with CAD lens modelling software1, if we can also easily prototype the lenses we design.

What are some materials and additive or subtractive 3D fabrication strategies that can make a clear lens with strong refraction and the ability to be polished?

1 Here is a helpful list of 37 different lens design & simulation programs.

答: 3D printing a refractive lens is possible using "printoptical technology" by LUXeXceL. It was developed for making perfectly smooth surfaces. With this technology there is no need for post-processing (grinding, polishing / coloring, etc.). </p>


问:
How do you move large industrial robots?
I know how they are moved on to a lorry/truck to be taken somewhere but when industrial robots are being built how are they moved around the production centre.</p>

答:
As jsotola's comment suggests, this Q&A site cannot give you what you need, and the best we can do is likely to be opinion-based. Here are some things to try anyway.

Keep reading this web site. Its pointillist specificity will eventually fill in its broad scope.

Many amateur robots differ from industrial robots only in degree (like size, power, precision, capability), not in kind. Search the web.

Some high school and college undergrad programs (e.g. FIRST) publish their designs. Search the web.

Manufacturers publish details about their products. Search the web.

Find one or more mentors to guide you.

Good luck! Even if you don't make a career of robotics, it's a great hobby.


问:
Robot performing soldering functions using Soldering iron
Is it possible to design and construct a Robot which can solder components using a Soldering iron on printed circuit boards?

If No, What are the limitations?

答:
Yes.  There are many soldering robots in existence today.  Unfortunately, they don't look very humanoid.  They are usually simply gantry style robot arms.  They are common on manufacturing lines.

Remember that a robot is just a machine.  And machines are designed to do a specific task, usually as efficiently as possible.  And this usually means simple, straightforward, and with the fewest extra degrees of freedom.  So a humanoid robot doesn't really make sense for this task.

Some quick google searches turn up many examples:


问:
Mobile Bot Maze Solving
I am using ROS melodic on ubuntu 18.04

I have a simple 2 wheeled mobile bot, with a lidar attached to it. It is kept at the entrance of a maze (any maze). The bot has to "solve" the maze, i.e. exit it, using the shortest possible path. We get 30 seconds first to "map" the maze.

First, using odometry and laser data, I used the slam gmapping package to try and create a map of the maze. I used a rudimentary algorithm (out of the three directions right ,left and straight, it choses the one with the most free space), just to check out if the mapping process is working out, and it indeed is. I am getting a fairly accurate occupancy grid till the time the algorithm runs properly (it runs into problems later).

From what I understand, after an appropriate map (occupancy grid) is obtained, we can apply graph algorithms like A*,RRT,RRT*etc. to obtain the optimum path.

However, I am confused regarding creating the appropriate map in the first place. I mean, I have the package working properly that will create the map for me, but what kind of algorithm should I implement to ensure a path is taken from the starting of the maze, to the end of the maze, and back to the start? (To create the appropriate map). The main issue here is that we also have to deduce weather we have reached the end of the maze or not.... We cannot hard-code the location of the maze as the algorithm has to be general.

In short, the main problem I have is not "how to create a map", but rather, "what path should the robot take so that the map it creates is appropriate for the purpose".

答:
Here's a video of a micromouse competition. The video starts with what I believe you're looking for - a mapping run.

How do you ensure you have appropriate coverage, though? It's up to you to define appropriate coverage. Is it okay to find one route to the end, or should you find all routes to the end?

If the end point isn't defined in advance then you need to explore the entire map. The most straightforward way to do that would be:

Collect the number of new available options,

Take the first available option and advance one space,

If it's not a dead end, go to 1 and repeat.

If it is a dead end, go back to the last intersection where you had new options and take the next available option.

If you're tracking/eliminating new options as you continue then when you fully exhaust one branch you should wind back up at your starting position and go down the next branch of possible options. You can do all kinds of tricks to try to optimize the mapping run, and you'll need safeguards to protect against pitfalls like what to do if you enter a grid location you've previously discovered (hint: treat it like a dead end!).

The type of data structures you choose to represent your map and the particular algorithms you use to build that map are your choice and will either make the problem really difficult or relatively simple, but that's what programming's all about!

Title: Mobile Bot Maze Solving


答:
what kind of algorithm should I implement to ensure a path is taken from the starting of the maze, to the end of the maze, and back to the start?

This is an exploration-exploitation problem. Please see this article for an overview of the challange and this paper for an example of how researchers approached a similar problem.

Basically, you need a decision criterea to govern the robot's behavior in a way so that it explores the environment without attempting to actually find the goal. As your robot learns more about the environment, it may stumble across the goal or find guides toward the goal that help it to exploit this goal. In practical RL research, this is often implemented by an exponentially decreasing exploration-exploitation tradeoff $\alpha=e^{-\beta t} \in [0,1]$.

Title: Mobile Bot Maze Solving

Body:
I am using ROS melodic on ubuntu 18.04

I have a simple 2 wheeled mobile bot, with a lidar attached to it. It is kept at the entrance of a maze (any maze). The bot has to "solve" the maze, i.e. exit it, using the shortest possible path. We get 30 seconds first to "map" the maze.

First, using odometry and laser data, I used the slam gmapping package to try and create a map of the maze. I used a rudimentary algorithm (out of the three directions right ,left and straight, it choses the one with the most free space), just to check out if the mapping process is working out, and it indeed is. I am getting a fairly accurate occupancy grid till the time the algorithm runs properly (it runs into problems later).

From what I understand, after an appropriate map (occupancy grid) is obtained, we can apply graph algorithms like A*,RRT,RRT*etc. to obtain the optimum path.

However, I am confused regarding creating the appropriate map in the first place. I mean, I have the package working properly that will create the map for me, but what kind of algorithm should I implement to ensure a path is taken from the starting of the maze, to the end of the maze, and back to the start? (To create the appropriate map). The main issue here is that we also have to deduce weather we have reached the end of the maze or not.... We cannot hard-code the location of the maze as the algorithm has to be general.

In short, the main problem I have is not "how to create a map", but rather, "what path should the robot take so that the map it creates is appropriate for the purpose".


问:
Aluminum vs Carbon Fiber
So building a quadrocopter from scratch HAS a lot of decision making, and I need some input on the material choice.

I have short listed Aluminum and Carbon Fiber for the Arms and support of the Quadrocopter.
I am a little short on cash to experiment with both of them.

So considering that I have enough money to buy either of those, and assuming that I have access to general tools like a Table Saw, Horizontal Band Saw, CNC Router and a Water jet.

What would be a better material to work with

EDIT:

I will be deciding the specs around the frame so as to allow me some design liberty. So right now, my goal is to assemble a very durable, as-light-as possible frame, which can withstand a lot of experimentation on the electrical side.

答:
CF is lighter but you definitively need to know your source, many of the inexpensive tubes are quite brittle. In any case I do not recommend drilling holes in the tube use clamps.
Aluminium is somewhat heavier and will transmit vibration (balance your motors and props) but is readily available cheaper and easier to work with. For a smaller craft I would use aluminium anything over 550 quality carbon </p>

Title: Aluminum vs Carbon Fiber


问:
Creating a custom msg in ros2
I have a package with two nodes, that are communicating internally. For that reason I would like to create a custom msg to transfer data between them.
I've followed this tutorial, which basically sets the following points:

add msg/Custom.msg with the message content

add the following to package.xml:

  <build_depend>rosidl_default_generators</build_depend>
  <exec_depend>rosidl_default_runtime</exec_depend>
  <member_of_group>rosidl_interface_packages</member_of_group>
```
<p>3.Add the following to CMakelists.txt:</p>
```find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}  "msg/Custom.msg")
```

in your source: devenv/msg/custom.hpp

(please note that I don't use an interface package, as this is intra-package communication communication)

I can see that the file is generetade in :
build/devenv/rosidl_generator_cpp/devenv/msg/custom.hpp

No matter what I've tried, I can't include thie hpp file, what am I doing wrong?

答:
The short version is, you need to tell CMake where to find the targets generated for the interfaces and link your own executable/library targets to them. You can do this using the rosidl_target_interfaces macro on Galactic and below, or the rosidl_get_typesupport_target macro on Humble and newer.

Here's the long explanation.

In general, an interface package is recommended because it makes it easier to share the interface definitions with other packages and projects. However your situation of wanting to use the interface only within one single package is a completely valid use case, and it is supported. It's just not as easy to do.

The problem you are encountering is occurring because when you add an interface, the rosidl_generate_interfaces CMake macro is creating a bunch of targets for generated header and source files and related compiled libraries behind the scenes. These targets and header files are installed automatically, but they don't get added to the default include or link paths for other targets in your CMakeLists.txt file. (In other words, all the rosidl machinery is oriented towards having separate interface packages.)

In order to solve your problem, you need to find the target that is generated by the rosidl machinery and link your node(s) to it. That will bring in the include and link paths, allowing your own code to find the generated header files from the same package.

In ROS 2 Galactic and lower, this is done using the rosidl_target_interfaces macro.

So if I add some interfaces to be generated using the PROJECT_NAME as the name of the interfaces target:

```<code>rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/MyInterface.msg"
)
</code>```

And assuming I have a node executable named my_node (the approach is identical for a library if you are building component nodes), I can fix the include and linking problem with this line:

```<code>rosidl_target_interfaces(my_node ${PROJECT_NAME} "rosidl_typesupport_cpp")
</code>```

If you are using ROS 2 Humble or newer (or Rolling), then there is a better approach available now. Replace the above line with these two lines:

```<code>rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} "rosidl_typesupport_cpp")
target_link_libraries(my_node "${cpp_typesupport_target}")
</code>```

This new approach is preferred because it gets the target, which potentially supports modern CMake target-based information sharing.

For an example of this in practice, see the common_interfaces package. This package provides many interfaces, but it also tests them. In order for the tests to compile they have to be able to find the interfaces provided by the same package.

Galactic and earlier

Humble and later

Title: Creating a custom msg in ros2

Body:
The short version is, you need to tell CMake where to find the targets generated for the interfaces and link your own executable/library targets to them. You can do this using the rosidl_target_interfaces macro on Galactic and below, or the rosidl_get_typesupport_target macro on Humble and newer.

Here's the long explanation.

In general, an interface package is recommended because it makes it easier to share the interface definitions with other packages and projects. However your situation of wanting to use the interface only within one single package is a completely valid use case, and it is supported. It's just not as easy to do.

The problem you are encountering is occurring because when you add an interface, the rosidl_generate_interfaces CMake macro is creating a bunch of targets for generated header and source files and related compiled libraries behind the scenes. These targets and header files are installed automatically, but they don't get added to the default include or link paths for other targets in your CMakeLists.txt file. (In other words, all the rosidl machinery is oriented towards having separate interface packages.)

In order to solve your problem, you need to find the target that is generated by the rosidl machinery and link your node(s) to it. That will bring in the include and link paths, allowing your own code to find the generated header files from the same package.

In ROS 2 Galactic and lower, this is done using the rosidl_target_interfaces macro.

So if I add some interfaces to be generated using the PROJECT_NAME as the name of the interfaces target:

rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/MyInterface.msg"
)

And assuming I have a node executable named my_node (the approach is identical for a library if you are building component nodes), I can fix the include and linking problem with this line:

rosidl_target_interfaces(my_node ${PROJECT_NAME} "rosidl_typesupport_cpp")

If you are using ROS 2 Humble or newer (or Rolling), then there is a better approach available now. Replace the above line with these two lines:

rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} "rosidl_typesupport_cpp")
target_link_libraries(my_node "${cpp_typesupport_target}")

This new approach is preferred because it gets the target, which potentially supports modern CMake target-based information sharing.

For an example of this in practice, see the common_interfaces package. This package provides many interfaces, but it also tests them. In order for the tests to compile they have to be able to find the interfaces provided by the same package.

Galactic and earlier

Humble and later


问:
Inverse kinematics for 2DOF robotic arm in 3D
i am trying to find the inverse kinematics for quadrotor with 2Dof robotic arm, which has first joint rotation axis perpendicular with second joint. So, for the inverse kinematics i use two equations

theta 1 = atan2(z,y)

theta 2 = atan2(x, (sqrt(z^2 + y^2)-L1)), where x,y,z are end effector position

If I use these two solution in jacobean matrix for finding the joint velocities: thetadot = pinv(J)*(x,y,z)dot, at some point i have singular configuration. For finding the determinent of jacobean matrix, i consider the the determinant of the (J'*J) because my jacobean is a 3 * 2 matrix.

So my questions are

are two equations for finding theta 1 and theta 2 correct?

how can I avoid the singular configuration?

when the jacobean matrix is zero, how can i find the joint velocities?

答:
without a daring it is hard to tell if the equations are correct. L1 is not explained, exact configuration is also unclear.

The simplest way is to see if at the considered pose you are at or near a singular pose is to check if determinant is zero or approaching zero. The simplest hack to void a singular pose is to just add a small offset to the point considered in the direction of your path. The offset should be large enough to not trigger the singularity check, i.e. the determinant at the offset point should not be zero or near zero. What near zero is, is your decision. The smaller the threshold, the more precise your robot will be, but, since you get closer to a singular position, your robot's on path velocity will be slower. This is due to the fact, that at the singular point, you would need infinite velocity on at least one axis to keep a constant on path velocity, so as you approach the singular pose the maximum speed of your axis will determine a slower and slower on path velocity. Adding a large offset to the point(s) in question will cause a path deviation on the robot. The larger the path deviation, the less velocity you will use and the more precision you lose. So it is a tradeoff between precision and on path velocity.

You cannot. I mean, even if you can, it does not help you, since at least one axis will need to have infinite velocity to maintain a constant, non-zero on path velocity. You can define a (hyper) sphere around the singular pose and just do not bother with anything inside that sphere. If you would end up inside, just go on path to the next point outside the sphere. Again, how large the sphere is, is up to you, the larger the sphere, the faster your on path velocity will be, but you will have a lower precision.


问:
Extract the potential energy from the gravity vector
I have a recursive Newton Euler algorithm from which I can compute the gravity vector.
My question is, which is the better way to compute the potential energy?
I know the following relation between gravity vector and potential energy
$$\textbf{g} = \left( \frac{\partial U}{\partial q}\right)^T$$
so in theory I could integrate numerically and get the potential energy, but since it is a gradient I'm not sure how to proceed. Of course I can compute it just computing all the contribution of the potential energy of each link knowing the mass and the center of gravity but I would like to know if there is a smarter and faster way to get it.

答:
You don't need to do an integral. The difference in gravitational potential between two points is independent of the path to get from one to the other. Evaluate the potential at each endpoint and subtract.

(Assuming your system is non-dissipative, non-relativistic, etc.)


答:
One thing to watch out for is that many of the additive or extrusion-based 3D printers will leave small gaps between the beads of plastic that they lay down.  Even if you polish the surface, the interior will be very poor optically.

You may want to look at Selective Laser Sintering (SLS) to create a finished product that is more uniformly solid.

Title: Is it practical to 3D print a refractive lens?

Body:
A lot of awesome optics projects like hacking cameras and projectors become possible with CAD lens modelling software1, if we can also easily prototype the lenses we design.

What are some materials and additive or subtractive 3D fabrication strategies that can make a clear lens with strong refraction and the ability to be polished?

1 Here is a helpful list of 37 different lens design & simulation programs.


问:
Can ROS run on a Raspberry Pi?
Can ROS run on a Raspberry Pi?

ROS is resigned to run on a network of machines, with different machines, even different cores on the same machine doing different jobs. Can one of those machines be a Raspberry Pi?

I am considering using an R-Pi as the EtherCAT master on a mobile robot, communicating with the main PC over WiFi, using a dongle.

Can an R-Pi even run ROS at all?

Would an R-Pi have enough processing power to do some 1kHz servoing?

Would it be possible to run some servoing on the host through the WiFi connecion?

答:
The official RaspberryPi operating system is a version of Debian, but there's also an ArchLinux version on their website.

Despite ROS's claim of being cross-platform, they only officially support Ubuntu at the moment. However, experimental installations have been made for the following OSes, according to ros.org:

OS X (Homebrew)

Fedora

Gentoo

OpenSUSE

Debian

Arch Linux

Windows

While I don't have any first-hand experience (my two Pis are shamefully sitting in the corner), ros.org has a quick and dirty setup guide.

There are similar instructions on answers.ros.org.

In case you run into any problems, the RaspberryPi forums might also be of some help. And, of course, SE's got it's very own PI.SE (Thanks to @Jivings and @ppumkin for the reminder).

Otherwise, just google "ros raspberry pi" and you should find plenty more information.

Title: Can ROS run on a Raspberry Pi?


问:
What is the difference between RC motors for cars and helicopters?
I am working on a robot with focus on speed. At the moment I am looking for a suitable motor but it would help if I understood the difference between the various options.

To provide some background, I have not worked with RC model components before, but I think this is the only place for me to find the components needed for my robot, such as the motor.

I have already figured out how much power the motor needs to accelerate my robot as desired, taking energy conversion efficiency and tractional resistance into account. It's about 170 watts, depending on the final weight.

To limit my search further, I need to decide on either using a RC car motor or a RC helicopter motor now, but I don't understand the difference between these options.

Focussing on brushless motors (if that matters), what are the differences between RC car and RC helicopter motors? What needs to be taken into account when choosing between them?

答:
i am a electrician . inrunners and outrunners are not DC motors! they are 3 phase motors like in industry . your speed control takes DC and uses electronics to change the DC into a pulsating DC ,in the shape of a AC 3 phase sine wave .and changes the frequency at your command .this is known as a frequency drive .
     inrunners spin about 65k rpm . after they get to a larger size they spin 40k rpm . outrunners spin 40k . outrunners put out more than twice the torque . outrunners are more efficient . this means more run time . outrunners dissipate heat faster and do not need cool down time if set up correctly .
     to pick a outrunner look for one about the same weight pick the highest KV for that frame size , pay attention to the voltage .
     now you have more than twice the torque . use it . start with twice the amount of teeth on your pinion , or change your spurr and pinion to get half the gear ratio .then go lower until the motor gets worm to the touch. NOT HOT .
     GOOD LUCK .</p>


问:
Why doesn't yaw angle return to its 0 state after rotations?
I'm using STM32F4 mcu with MPU6050 on it. I want to get very accurate yaw angle using gyroscope with Madgwick filter. I tried lots of things: with and without gyro thresholds, with and without acceletometer, with and without other gyro axes. I also tried all gyro sensitivities, but nothing of this help. So about the problem - When I move and rotate controller from specific place and get it back after few seconds - yaw angle doesn't come back to zero:

(Start placement with yaw==0)

(In this picture yaw is also zero, but you can see, that pcb is not on the original place)

The Madgwick filter:

void MadgwickAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az) {
    float recipNorm;
    float recipNormAccel;
    float recipNormS;
    float s0, s1, s2, s3;
    float s0_view, s1_view, s2_view, s3_view;
    float qDot1, qDot2, qDot3, qDot4;
    float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3;

    // Rate of change of quaternion from gyroscope
    qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz);
    qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy);
    qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx);
    qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx);

    // Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
    if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {

        // Normalise accelerometer measurement
        recipNormAccel = invSqrt(ax * ax + ay * ay + az * az);
        ax *= recipNormAccel;
        ay *= recipNormAccel;
        az *= recipNormAccel;

        // Auxiliary variables to avoid repeated arithmetic
        _2q0 = 2.0f * q0;
        _2q1 = 2.0f * q1;
        _2q2 = 2.0f * q2;
        _2q3 = 2.0f * q3;
        _4q0 = 4.0f * q0;
        _4q1 = 4.0f * q1;
        _4q2 = 4.0f * q2;
        _8q1 = 8.0f * q1;
        _8q2 = 8.0f * q2;
        q0q0 = q0 * q0;
        q1q1 = q1 * q1;
        q2q2 = q2 * q2;
        q3q3 = q3 * q3;

        // Gradient decent algorithm corrective step
        s0_view = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
        s1_view = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
        s2_view = 4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
        s3_view = 4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay;
        recipNormS = invSqrt(s0_view * s0_view + s1_view * s1_view + s2_view * s2_view + s3_view * s3_view); // normalise step magnitude
        s0 = s0_view * recipNormS;
        s1 = s1_view * recipNormS;
        s2 = s2_view * recipNormS;
        s3 = s3_view * recipNormS;

        // Apply feedback step
        qDot1 -= beta * s0;
        qDot2 -= beta * s1;
        qDot3 -= beta * s2;
        qDot4 -= beta * s3;
    }

    // Integrate rate of change of quaternion to yield quaternion
    q0 += qDot1 * (1.0f / sampleFreq);
    q1 += qDot2 * (1.0f / sampleFreq);
    q2 += qDot3 * (1.0f / sampleFreq);
    q3 += qDot4 * (1.0f / sampleFreq);

    // Normalise quaternion
    recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
    q0 *= recipNorm;
    q1 *= recipNorm;
    q2 *= recipNorm;
    q3 *= recipNorm;
}

float invSqrt(float x) {
    if (x != 0)
        return 1.0f / sqrtf(x);
    return 1;
}
```
<p>This is how I use the filter:</p>
<pre class="lang-c prettyprint-override"><code>#define GYRO_Y_THRESH 0.0045

void Process_IMU()
{
    //read raw data
    uint8_t data[14];
    uint8_t reg = ACCEL_XOUT_H;
    uint8_t mpu_address = MPU6050_ADDRESS_DEFAULT;

    while(HAL_I2C_Master_Transmit(_MPU6050_I2C,(uint16_t)mpu_address,&reg,1,1000) != HAL_OK);
    while(HAL_I2C_Master_Receive(_MPU6050_I2C, (uint16_t)mpu_address, data, 14, 1000) != HAL_OK);

    /*-------- Accel ---------*/
    Accel_x = (int16_t)((int16_t)( data[0] << 8 ) | data[1]);
    Accel_y = (int16_t)((int16_t)( data[2] << 8 ) | data[3]);
    Accel_z = (int16_t)((int16_t)( data[4] << 8 ) | data[5]);

    /*-------- Gyrometer --------*/
    Gyro_x = (int16_t)((int16_t)( data[8] << 8  ) | data[9]);
    Gyro_y = (int16_t)((int16_t)( data[10] << 8 ) | data[11]);
    Gyro_z = (int16_t)((int16_t)( data[12] << 8 ) | data[13]);

    Accel_X = (float)((int32_t)Accel_x - Accel_x_bias)/(float)accel_sensitivity;
    Accel_Y = (float)((int32_t)Accel_y - Accel_y_bias)/(float)accel_sensitivity;
    Accel_Z = (float)((int32_t)Accel_z - Accel_z_bias)/(float)accel_sensitivity;

    Gyro_X =  (float)(((int32_t)Gyro_x - Gyro_x_bias)/(float)gyro_sensitivity)*M_PI/180.0 * STUPID_PRES;
    Gyro_Y =  (float)(((int32_t)Gyro_y - Gyro_y_bias)/(float)gyro_sensitivity)*M_PI/180.0 * STUPID_PRES;
    Gyro_Z =  (float)(((int32_t)Gyro_z - Gyro_z_bias)/(float)gyro_sensitivity)*M_PI/180.0 * STUPID_PRES;

    if (fabs(Gyro_Y ) < GYRO_Y_THRESH)
        Gyro_Y = 0;

    MadgwickAHRSupdateIMU(0,0,-Gyro_Y ,0,0,-accel_sensitivity);

}
</code>```

(I don't want to use accelerometer values, because when I use them yaw angle starts changing when I move pcb without rotating it. And also roll and pitch start increasing even if I do not rotate pcb in these axes)

Now I use ACCEL_FS_4 sensitivity for acceletometer and GYRO_FS_2000 for gyro.

I also calibrate gyro and accelerometer at the begin.

What should I do to prevent this? I want yaw angle to come back to zero after some rotations.

答:
You can't. The down vector is fixed because gravity always points down, and you can measure accelerations (gravity) with the accelerometers.

You can't fix heading without a magnetometer at least, to measure magnetic North, and even with a magnetometer you can have issues with nearby ferrous objects, electric fields, etc.

But with no magnetometer you can't fix your yaw (heading!) angle. Remember your gyroscopes are measuring angular velocity, not angular position, so your yaw (heading!) angle will drift with gyro bias.


问:
A short-range alternative to LiDAR
LiDAR is a very popular choice for long distance applications such as autonomous vehicles. I'm looking for a device that can give me a 3-dimensional representation of a close proximity environment (e.g. a 5-10 meter diameter "sphere" of points.) Are there cheaper versions of LiDAR that can fit this situation, or is there another technology to look at instead?

I've considered cameras, but would prefer a more "physical" representation of the surroundings.

答:
This is borderline into a "shopping question" that aren't a great fit for the site. To that end I'm going to answer you in as generic a way as possible.

Commonly available LIDARs can have ranges out to ~100m but there are many of them with shorter maximum ranges or effective ranges in the 10s of meters. Some drop down into single digit meters of range. There's a large range of options with different fields of view. There are multi-beam spinning ones, the more classic single plane ones. And it can drop down to single beam ones too.

There are specialized ones also that are focused on very close range. Think milimeters not meters.

Alternative technologies can include depth cameras. (Unlike your assertion they do provide 3D information like a LIDAR, and often provide color information as well.) The most classic is stereo cameras which rely on texture in the environment. There are also classes of structured light cameras that project patterns usually in IR out. There are limitations of structured light is bright environments such as outside.

There's also ultrasonic sensors which are much cheaper but much coarser in their results.

The cost of different sensors can range by 6 orders of magnitude and their update rates can range potentially by 3 or 4. The field of view is very variable, from 360 to single point.

All of this comes together to say that there's a lot of options out there and is why we don't want shopping questions. Because we can't make all the design tradeoffs without actually fully knowing your requirements of your application which can't be effectively captured in a post on this forum.

Title: A short-range alternative to LiDAR


问:
Simplest way to drive a Nema 17? Without Breadboard and all that gobbledygook
I would like to setup a nema 17 with a belt... is there like some chip board / module with everything built in where I can plug in the stepper and program it to go forward and back without all the crazy breadboard wires and tons of gobbledygook... everytime I look up how to hookup a Stepper motor its got all this crazy wires and everything... you think a company would have made like an easy module to program without that breadboard... will it work on one of them small Aurdionos.. I got me a bunch of them laying around</p>

答: You want to google "stepper motor arduino shield". That add-on item plugs into (onto) an arduino without crazy wires. You will need wires to power the arduino, to power the motor controller (perhaps shared with the arduino), and of course the wires of the motor itself. Those are necessary, not crazy. Raspberry Pis accept similar add-on items, called "hats".</p>


问:
Compensation of sudden impacts/shocks in adaptive AHRS sensor fusion algorithms

Background

I have a 9-DOF MEMS-IMU and trying to estimate the orientation (roll, pitch and yaw) in scenarios (e.g. car crash) where sudden shocks (mainly linear) lead to high external accelerations and the orientation estimate might diverge due to the large out-of range acceleration peaks. There a lot of approaches in the literature to overcome such disturbances. Adaptive filters are used that change their gain and give more trust to the gyroscope in case of external acceleration (eg. Kalman Filter - adopts the covariance matrix, Complementary Filter adopts the gain, etc.).

From R. Valenti there exists a quaternion-based adaptive complementary filter which works quite well by adapting the gain in presence of external linear accelerations. There is also an official Matlab implementation.

Problem

Imagine the IMU is mounted in the head of a crash-test dummy. During the short-term impact it is assumed that acceloremeter is saturated. Now the algorithm gives more trust to the gyroscope.

But what happens if the gyroscope gets a rotational "knock" during the impact that just consists of a few degrees but also leads to saturation of the gyroscope during the shock? The orientation estimation will get erroneous.

Question

Are there any theoretical or practical approaches which somehow deal with this kind of problem? Maybe if I know the pattern of the shock I can estimate the saturated/clipped/censored gyroscope data?

答:
At the highest level an estimator like a Kalman filter is estimating an unknown system state based on a model and measurements.

Your sensor has shortcomings such as linear and angular clipping when the shock is too high which is limiting your ability to observe the system and consequently the basic model which assumes that the measurements are proportional are no longer accurate.

If you are unable to improve your measurements (Which you appear to be requiring in this question.) you will need to improve your model. The adaptive filters that you reference are a step in that direction. However in your case you will want to improve your model to be able to handle the saturation of the measurement. Since the acceleration and potentially rates from the gyros are now no longer always known they too will become part of the estimated state. Where the measured values have high confidence when they're being measured directly, but when saturated they will need to be discounted.

And you will then need to extend your model of the system to estimate the evolution of the newly added state model updates which will let your filter update the estimated values of the acceleration and velocities when the sensor is saturated and not reporting accurately.

To build up this model and how it updates, you can either derive/estimate it analytically based on your understanding of the geometric and dynamic constraints on the system. Or you could setup some controlled experiments to empirically develop a model. For your experiments you'll likely want to bring in an external sensor such as a motion capture system to validate and train your model generation. With the model extended to estimate the acceleration and rates while the sensor is saturated you can get an improved result.

Note that your results will vary greatly based on how well you can improve the model update. If you know the situation and can get good ground truth data in all the expected configurations you can possibly get very good data. However if there are a lot more parts of the system which are variable and there's a lot of time when the sensors are saturated this approach will not work as well.

You also are going directly to an online estimator which is required for a live system, however if you're doing crash test reconstruction you could consider using much more complicated model fitting estimation which will batch process afterwards and estimate the values across the period of saturation by taking into account the state of the system before and afterwards. Versus an online filter which only can take into account data collected in the past.

As a side note: This sounds like a moderately complicated issue to resolve as asked and I worry that this is a bit of an X-Y problem where you're presuming an approach to the solution that's sub optimal versus asking for help on the underlying issue. There may be alternative approaches to solving your problem that are easier.


问:
Will using a 1:50 cycloidal drive on a 10,000 RPM brushless motor actually spin the output shaft at 200 RPM with 50x the torque of the motor?
In short, I'm trying to build a high-torque and high-RPM robotic arm, and I think brushless motors are the best compromise. The motors I'm considering are 400KV, and are supposed to run on 6S. Are there any glaring errors with my idea?</p>

答:
Almost...

You will have some losses in torque due to fiction and the elastic deformation needed for the cycloidal drive.

Your math, other then losses, is fine, but you have to consider also the technological parameters. You have to make sure that the gearbox supports 10.000 rpm (it might overheat if it was designed as a lower speed gearbox) and that it is rated for the torque input and output (the internal components and gears might get damaged if you are over the rated torque). Furthermore, there is more to a gearbox, then just axial load and rpm. You have to make sure that the radial loads on the gearbox are also in spec, otherwise you might snap the shaft off or damage the bearings.

As far as I know, current large scale industrial robots, use even higher gearbox ratios.