Skip to content

Commit a7e1f82

Browse files
Update 2d_transforms.md
1 parent d4dd110 commit a7e1f82

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

docs/2d_transforms.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ The example I am going to present will make some of you react like this:
44

55
![really](img/really.jpg)
66

7-
I say this because, for some of you ,it will be absolutely obvious... in retrospective.
7+
I say this because it will be absolutely obvious... in retrospective.
88

9-
On the other hand, I have seen **this same code** being used in open source projects.
9+
On the other hand, I have seen **this same code** being used in multiple open source projects.
1010

1111
Projects with hundreds of Github stars missed this (apparently obvious) opportunity for optimization.
1212

13-
Have a look to: [Speed up improvement for laserOdometry and scanRegister (20%)](https://github.com/laboshinl/loam_velodyne/pull/20)
13+
A notable example is: [Speed up improvement for laserOdometry and scanRegister (20%)](https://github.com/laboshinl/loam_velodyne/pull/20)
1414

1515
## 2D transforms
1616

@@ -21,7 +21,7 @@ double x1 = x*cos(ang) - y*sin(ang) + tx;
2121
double y1 = x*sin(ang) + y*cos(ang) + ty;
2222
```
2323
24-
People with a trained eye and a little of trigonometric background will immediately recognize the [affine transform of a 2D point], commonly used in computer graphics or robotics.
24+
People with a trained eye (and a little of trigonometric background) will immediately recognize the [affine transform of a 2D point], commonly used in computer graphics and robotics.
2525
2626
Don't you see anything we can do better? Of course:
2727
@@ -35,7 +35,7 @@ double y1 = x*Sin + y*Cos + ty;
3535
The cost of trigonometric functions is relatively high and there is absolutely no reason to compute twice the same value.
3636
The latter code will be 2x times faster then the former, because the cost of multiplication and sum is really low compared with `sin()` and `cos()`.
3737

38-
In general, if the number of potential angles you need to test is finite, consider to use look-up-table where you can store pre-computed values.
38+
In general, if the number of potential angles you need to test is not extremely high, consider to use look-up-table where you can store pre-computed values.
3939

4040
This is the case, for instance, of laser scan data, that needs to be converted from polar coordinates to cartesian ones.
4141

@@ -46,27 +46,27 @@ A naive implementation would invoke trigonometric functions for each point (in t
4646
```c++
4747
// Conceptual operation (inefficient)
4848
// Data is usually stored in a vector of distances
49-
std::vector<double> scan_distance;
50-
std::vector<Pos2D> cartesian_points;
49+
std::vector<double> scan_distance; // the input
50+
std::vector<Pos2D> cartesian_points; // the output
5151

5252
cartesian_points.reserve( scan_distance.size() );
5353

5454
for(int i=0; i<scan_distance.size(); i++)
5555
{
56-
const double dist = scan_distance[i];
57-
const double angle = angle_minimum + (angle_increment*i);
58-
double x = dist*cos(angle);
59-
double y = dist*sin(angle);
60-
cartesian_points.push_back( Pos2D(x,y) );
56+
const double dist = scan_distance[i];
57+
const double angle = angle_minimum + (angle_increment*i);
58+
double x = dist*cos(angle);
59+
double y = dist*sin(angle);
60+
cartesian_points.push_back( Pos2D(x,y) );
6161
}
6262
```
6363

64-
That is unecessary inefficient, because:
64+
But we should consider that:
6565

6666
- **angle_minimum** and **angle_increment** are constants that never change.
6767
- the size of the **scan_distance** is constant too (not its content, of course).
6868

69-
This is the perfect example where a LUT makes sense and can dramatically improve performance.
69+
This is the perfect example where a LUT makes sense and will dramatically improve performance.
7070

7171
```c++
7272
//------ To do only ONCE -------
@@ -75,9 +75,9 @@ std::vector<double> LUT_sin;
7575

7676
for(int i=0; i<scan_distance.size(); i++)
7777
{
78-
const double angle = angle_minimum + (angle_increment*i);
79-
LUT_cos.push_back( cos(angle) );
80-
LUT_sin.push_back( sin(angle) );
78+
const double angle = angle_minimum + (angle_increment*i);
79+
LUT_cos.push_back( cos(angle) );
80+
LUT_sin.push_back( sin(angle) );
8181
}
8282

8383
// ----- The efficient scan conversion ------
@@ -88,17 +88,17 @@ cartesian_points.reserve( scan_distance.size() );
8888

8989
for(int i=0; i<scan_distance.size(); i++)
9090
{
91-
const double dist = scan_distance[i];
92-
double x = dist*LUT_cos[i];
93-
double y = dist*LUT_sin[i];
94-
cartesian_points.push_back( Pos2D(x,y) );
91+
const double dist = scan_distance[i];
92+
double x = dist*LUT_cos[i];
93+
double y = dist*LUT_sin[i];
94+
cartesian_points.push_back( Pos2D(x,y) );
9595
}
9696
```
9797

9898
# Lessons to take home
9999

100-
This is a simple example; what you should learn from it is that, whenever an operation is expensive to compute (SQL queries, stateless mathematical operations), you should consider to use a cached value and or to build a look-up-table.
100+
This is a simple example; what you should learn from this is that, whenever an operation is expensive to compute (SQL queries, stateless mathematical operations), you should consider to use a cached value and or to build a look-up-table.
101101

102-
But, as always, measure first, to be sure that the optimization is actually relevant ;)
102+
But, as always, **measure first** to be sure that the optimization is actually relevant ;)
103103

104104

0 commit comments

Comments
 (0)