Introduction A robotic arm, or robot manipulator can be designed to perform any desired task such as welding, gripping, spinning, etc. There are countless applications for this automates. In the automotive industry, they are usually used to perform a variety of tasks such as welding, part placement, painting and some other tasks. In some circumstances, robotics arm are desired to have close emulation to the human hand, a good example is the bomb disarmament and disposal. How to program a robotic manipulator? Robotics manipulators can be divided in two classes: serial and parallel. Each of it has its own advantages. However, serial robots are broadly used. Several companies have released their own robots different capabilities. Fanuc, ABB, KUKA, or whatever brand you use. I've seen everything is reduced to know the math. Each brand has their own platform to program the robot. But the math behind it is reduced to rotation and translation matrices. Which can be converted to different representation such as the angle axis representation, Euler angle representation, etc. Let's move it! I have done a small script that moves the robot in different axis. All this motions can be described with rotation matrices. The following simulation shows a KUKA robot performing 180° rotations alogn a fixed point in space.
1 Comment
IntroductionAugmented, virtual or mixed reality? Still are some confusion due to the semantics in this area. But what it matter to me are the myriad of applications that are currently under development. Decided to explore the field, I have done my own application (simple enough). From my opinion, I consider this application that falls into the Augmented/Mixed reality approach, it overlays an object on top of scenario making the object to appear par of the scene. How does it work? While the approach can be describe very simple, getting it to work seems quite hard. For this application I have used a state of the art detector/tracker called CMT (Clustering of Static-Adaptive Correspondences for Deformable Object Tracking), while I could go for hours trying to explain the overall approach. I have focused in how I could use it. However, there is no restriction in what type of algorithm or approach is selected, but usually is nice to be able to have an algorithm that gives features such as plane rotation, scale change, and handles some deformation, most of the point-based algorithms are able to handle this up to some point. Descriptors such as FAST, ORB, BRISK and some others can be used to accomplish this task (in fact, CMT uses BRISK in a consensus manner. Hint!). Now we are able to have a model of the target and calculate plane rotations, scale changes, and probably some homography of the object for out-of-plane rotation. Another set of algorithms that could be used are those that are template matching based such as the cross-correlation, some extra implementation would be necessary to account for scale change. However, this type of approaches do not handle well out-plane-rotations. ResultsI have placed a Kalman Filter that estimates the center pixel coordinates, the height and width of the target (for more about the Kalman Filter, you can visit my older post in the following link) with an outlier rejection mechanism (the famous Mahalanobis distance) to be able to remain in the last position if the tracker/dectetor is lost. The overall approach works well with targets with a lot of features at somewhere around the 25FPS.
Captain's log: week 1
Decided to do my own c++ tutorial to get a better idea of what c++ is and the things we can do with it. I have decided instead to start with those topics that are usually more complex. I will try to explain each of the concepts and give different examples. Going from the theory to real applications.
Notes and Suggestions
Arrays
An array is a fixed collection of similar data type items placed in contiguous memory locations that can be individually referenced by adding an index to a unique identifier. Index in this contest will be the location of the information within the array.
Let's give several examples of how to declare array. int ball[5];
Remember, arrays in c++ start at index 0, in the previous example you can access the index 0,1,2,3 and 4.
The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs. Arrays can be initialized in different ways: int ball[5]={0,1,2,3,4}; int ball[]={0,1,2,3,4,5}; int ball[] {0,1,2,3,4,5};
All previous initialization are correct. The compiler can figure out the number of elements within an array at compiling time. Moreover, the equal sing is not longer needed.
int ball[];
However, the previous will cause a compiling error. The compiler won't be able to figure out the data stored in the array (there is no data declared) nor the array size. This will produce an error saying "storage size of 'ball' isn't known. A good programming practice is always at least to provide the size of the array, so the compiler knows the amount of memory needed.
Multidimensional Arrays
Arrays in c++ can have as many dimensions you require, 2, 3, or more dimensions. This is how we declare multidimensional arrays.
int balls[2][2];
The previous array will have 2 rows and 2 columns, all of them initialized with the value 0.
int balls[2][2]={{1,2},{4,3}};
The previous array will have 2 rows and 2 columns, initialized with the previous values.
Reading and writing data
Two write data in any array is just as simple as the following statement:
int ball[2]=5; int balls[2][1]=5;
The first example will write 5 at the index or position 2 of the array ball. The second example will write the value 5 in row 3 and column 2 of the array balls.
Two write data in an array, the following statement is allowed: int x=ball[2]; int y=balls[2][1];
The previous statements will assign to x and y the values located at index "2" in ball and the row "2" and column "1" in balls respectively.
Passing array to a function
We can pass entire arrays to a function as an argument, the best way to explain this is with an small code. This code will consist of an array that with be passed to a function, this function will print the values of the array.
#include <string> #include <iostream> using namespace std; void print_array (int arg[], int length) { for (int n=0; n<length; ++n) cout << arg[n] << ' '; cout << '\n'; } int main () { int array[] = {5, 10, 15}; //array declaration print_array (array,3); //call to function print_array return 0; }
Let's mention the key aspects of the previous example code. array is passed to the function print_array that is declared as void, this mean that the function won't have any return value.
Array and pointers
Beginners are usually reluctant to use pointers. My personal advice, Use them, do not be afraid. The sooner you learn the concept, the better. Pointers are used for code optimization, since we can use the value of variable without copying the value of the variable itself. There are also the only way to allocate memory in C/C++. A more specific use of pointers will be covered in another post, for now, let's focused in how are arrays and pointers related.
An array work similar to a pointer to the first element. an array can be used to be implicitly converted to the pointer of the proper type. int array [5]; int *ptr_array; ptr_array=array;
After that, array and ptr_array will have similar properties, the main difference being that ptr_array can be assigned a different address. However, array can be assigned anything, and will always represent the same block of 5 elements of type int. While the ptr_array can be assigned to ptr_array, the following assignment will not have much meaning in C++, meaning that the assignment is not bidirectional.
array = ptr_array;
Also the operator [] can be the same when dealing with pointers, take a look at the next example.
array[5] = 1; // a [offset of 5] = 0 *(array+5) = 1; // pointed to by (a+5) = 0
The previous 2 expressions are equivalent. An array can be used as a pointer to its first element. Let's make another example.
#include <iostream> using namespace std; void display_array(int *ptr, int t) { for(int i=0;i<=t;i++) { cout<<*ptr+i<<endl; } } int main() { int lenght=2; int array[]={1,3,5}; display_array(array, lenght); return 0; } Output 1 2 3
As you can see, the previous example calls a function display_array, this function will take as an argument a pointer. As we can see, the pointer will take an address of the first value of the array. In terms of optimization, it might not have a difference with a function call by value. But in an array of thousands of values, it will make a huge difference, since every call by value will copy the data of array.
The previous program is equivalent to the following program. #include <iostream> using namespace std; void display_array(int ptr[], int t) { for(int i=0;i<=t;i++) { cout<<*ptr+i<<endl; } } int main() { int lenght=2; int array[]={1,3,5}; display_array(array, lenght); return 0; } Output 1 2 3
So, the 2 following function declarations are the same.
void display_array(int ptr[], int t) void display_array(int *ptr, int t)
This is only valid for arrays. But some programmers prefer to work with "[]" when working with arrays and functions. The programmer will know the function is expecting an array, on the compiler side, there will be no difference at all.
Enum Types
Data types allows to write programs in a more understandable way, it allows every possible value to be declared as a symbolic constant. Each enumerator is automatically assigned with an integer value depending of its position in the enumeration list, starting from 0 and increasing the number. The structure of the enumerated data types is following.
enum type { CONST_0, // assigned 0 CONST_1, // assigned 1 . . . CONST_n, // assigned n };
The enum class can be forced to start in a different integer value, if a different value is assigned. Let's see the following example
enum CARS\n{\n NISSAN=-2, // assigned -2\n CHEVROLET, // assigned -1 \n TESLA, // assigned 0 \n FORD, // assigned 1 \n KIA, // assigned 2 \n FIAT=6, \n BMW, // assigned 7 \n MERCEDEZ, // assigned 8 \n};\n Captain's log: week 2Structs
Let's go into the object oriented programming, and let's make it simple. What about if we need more than one variable to represent, let's say a car. This car has characteristics such as model, manufacturer, year, state, and some others.
std::string model; std::string state; int year;
Let's assume now that you have a data base of 3000 cars, you need to have control over each of the cars. Will you have to declare for each of the 3000 cars each of the variables just mentioned? The answer is no. We can create objects or structs (structure).
Declaring Structs
The usual form a struct is the following, there are some other variants, depending of the application.
struct type_name
{
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
};
Another way that an struct can be declared is the following.:
struct type_name
{
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
}object_names;
The difference lays that in the last one, the objects are declared with the struct. EIther way, both are valid in c++. Let's return to the car examples, and let's create a struct.
class car { std::string model; std::string state; int year; };
IMPORTANT: Do not forget the semi colon at the end.
Let's now use our example in a real program.
#include <iostream> #include <string> using namespace std; struct car { std::string model; std::string state; int year; }; // C++11 only car FORD={"Focus","Florida",2015}; car Tesla={"Models","California",2016}; car Chevrolet={"Camaro","Texas",2015}; int main() { cout<<"Display model information : "<<FORD.model<<endl; cout<<"Display model information : "<<Tesla.model<<endl; cout<<"Display model information : "<<Chevrolet.model<<endl; } Output Display model information : Focus Display model information : Models Display model information : Camaro
As we can see, this is pretty simple. Also, we have learned how to initialize the variables in very organized manner. Just keep in mind that the initialization done in the previous example is only available for c++11, make sure to compile with such capabilities.
In the similar way we accessed the information in our objects, we can assign them values. #include <iostream> #include <string> using namespace std; struct car { std::string model; std::string state; int year; }; // C++11 only car FORD={"Focus","Florida",2015}; car Tesla={"Models","California",2016}; car Chevrolet={"Camaro","Texas",2015}; int main() { FORD.year=2014; Tesla.state="Nevada"; Chevrolet.model="Blazer"; cout<<"Display year information : "<<FORD.year<<endl; cout<<"Display state information state : "<<Tesla.state<<endl; cout<<"Display model information model : "<<Chevrolet.model<<endl; } Display year information : 2014 Display state information state : Nevada Display model information model : Blazer
The values of the objects can be read or assigned using the structure object.member_name.
Nesting structs
While the following example could be valid, there might be better ways to represent it. But for sake of giving an example, we can consider the creation of another structure called driver. As you can see, we have declared right after the object. However, the programmer can add more objects if needed.
#include <iostream> #include <string> using namespace std; struct Car { std::string model; std::string state; int year; }; struct Driver { std::string last_name; std::string state; std::string job; int age; Car Nissan; }David; // C++11 only Car FORD={"Focus","Florida",2015}; Car Tesla={"Models","California",2016}; Car Chevrolet={"Camaro","Texas",2015}; int main() { David.last_name="Meyer"; David.job="Programmer"; David.age=28; David.Nissan.model="Altima"; David.Nissan.state="Georgia"; FORD.year=2014; Tesla.state="Nevada"; Chevrolet.model="Blazer"; cout<<"Display Last name information : "<<David.last_name<<endl; cout<<"Display Model information : "<<David.Nissan.model<<endl; cout<<"Display State information : "<<David.Nissan.state<<endl; }
We can see the structure call can be done following the hierarchy of the outermost structure that contains the nested structure. We can see that the two objects here are David and Nissan, the call it is done by David.Nissan to the object member of Nissan state. Take a look that Driver also has an object member state. To access to it we could do something like David.state. The call has to be done in a sequential manner up to reach the desired object member, Object_n,object_n-1,object_n-2.object.object_member.
Captain's log: week 3Object Oriented Programming
Object Oriented programming (OOP) was designed with the idea in mind of give to reduce the amount of code needed, and give an structure to the code easier to understand. Also to be able to reuse code in different applications. The Object oriented programming speaks for itself, we are going to program objects, and by objects, we can think about real life objects, that has properties and behave in different manners. Think about you are doing a database of the people that works in a middle-size company (around 50 employees). Each of those employees has different properties such as name, last name, age, position within the company, even people with the same position might do different things (we might consider this a different behavior). If we wouldn't have the OOP approach, can you imagine how many variables we should declare for each person within the company? A lot!.
Structs and classes are considered similar. However, programmers prefer to use classes when functions are declared within the class. Every object that surround us has many features or properties and behaviors. While we can't conceive an object without features, we can't conceive and object without its behavior. Meaning that there is a relationship with properties and behavior that we can't separate. Are we going to cover those strange concepts of OOP such as inheritance, encapsulation, abstraction, and polymorphism?. The answer is yes! We will. Be patient my young padawan, We will get there. Classes
Here we go, let's start with the very first thing you should know about OPP. Wait! You might have seen something similar before. Structs! Structures are pretty much classes that differ in the data flexibility.
struct Car { std::string model; std::string state; int year; }; class Car { public: std::string model; std::string state; int year; };
The two previous code snippets will get the same results. Also classes can be initialized in the same manner as structures.
You might be wondering why we have structs and classes. Moreover. What is that word within the class declaration that makes a reference to "public:". Let's discuss it. This is going to be the biggest difference (and probably the only one I have seen so far) among classes and structs. The access to the members of a class can be controlled while the access of the members of a structure are public by default. They are 3 different types of access within a class.
By default, object members are declared private, unless it is specified. For example, the following class has all its member private. Since public wasn't added. class Car { std::string model; std::string state; int year; void print_info() { cout<<"The year of "<<model<<" is "<< year<<" from "<< state<<endl; } };
A good programming practice is to declare the objects members private and the member functions public. Also, preceding members with the letter m will mean that is member of class. There are several rules out there to declare members. Something like this.
#include <iostream> #include <string> class Car { std::string m_model; std::string m_state; int m_year; public: void setCar(std::string model, std::string state, int year) { m_model = model; m_state = state; m_year = year; } void print_info() { std::cout<<"The year of "<<m_model<<" is "<< m_year<<" from "<< m_state<<std::endl; } }; int main() { Car car; car.setCar("Chevrolet","Florida",2014); car.print_info(); }
The year of Chevrolet is 2014 from Florida
Although, we don't have direct access to the variables, we can set them using the function setCar, and the information can be accessed using print_info. The different calling methods to functions can be implemented with classes and structures too. We will see that in a little bit.
Classes initialization
Constructors
A constructor is the proper way to initialize classes when the class is instantiated (declared). Constructors can be initialized with the default user-provided values. It is mandatory for a constructor to have the same name as the class. Also, constructors do not have return type.
#include <iostream> #include <string> class Car { std::string m_model; std::string m_state; int m_year; public: Car(std::string model, std::string state, int year) { m_model = model; m_state = state; m_year = year; } void print_info() { std::cout<<"The year of "<<m_model<<" is "<< m_year<<" from "<< m_state<<std::endl; } }; int main() { Car car("Chevrolet","Florida",2014); car.print_info(); }
In the previous code, we can see that the initialization of car takes places in the following code snippet.
Car(std::string model, std::string state, int year) { m_model = model; m_state = state; m_year = year; }
A more elegant and efficient way to initialize classes is using a member initialization list. The initialization list has the form a OOP code.
The following code shows the proper way of using the member initialization list. #include <iostream> #include <string> class Car { std::string m_model; std::string m_state; int m_year; public: Car(std::string model, std::string state, int year): m_model(model), m_state(state), m_year(year) { } void print_info() { std::cout<<"The year of "<<m_model<<" is "<< m_year<<" from "<< m_state<<std::endl; } }; int main() { Car car("Chevrolet","Florida",2014); car.print_info(); }
Let's take a closer look to the class initialization using member list. We can see now that there is no assignment needed withing the brackets. This type of initialization allows to pass arguments by value, or even by reference. Also, allows the uniform initialization or the member initialization list.
Car(const std::string &model,const std::string &state,const int &year)
The previous initialization is different to the following initialization, can you spot the difference?. Take a closer look, the variables were initialized using uniform initialization.
Car(std::string model, std::string state, int year): m_model{model}, m_state{state}, m_year{year} { } |
About meEvery venture in an unknown territory is exciting to me. I ended up working with autonomous robots using knowledge from fields such as; computer vision, Bayesian estimation, control theory, neural networks, and SLAM. I have always been fascinated by aerial and ground mobile vehicles. Thankfully I had the chance to work on algorithms that bring them to life. Archives |