├── lepton_camera
├── FLIR_Lepton_Data_Brief.pdf
├── src
│ ├── video
│ │ ├── CMakeLists.txt
│ │ └── lepton.cpp
│ └── SPI
│ │ ├── CMakeLists.txt
│ │ ├── SPI.h
│ │ └── SPI.cpp
├── README.md
├── package.xml
└── CMakeLists.txt
├── README.md
└── I2C_Lepton
├── FLIR_Lepton_Software_Interface_Description_Document_110_0144_03.pdf
├── README.md
├── main.cpp
├── I2C_Interface.h
└── I2C_Interface.cpp
/lepton_camera/FLIR_Lepton_Data_Brief.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PX4/Lepton/HEAD/lepton_camera/FLIR_Lepton_Data_Brief.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Lepton IR Camera ROS NODE
2 | Package is currently built and aims to establishing stable ROS node for Lepton IR camera.
3 |
--------------------------------------------------------------------------------
/lepton_camera/src/video/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Add executable leptonvideo
2 | add_executable (leptonvideo lepton.cpp )
3 | target_link_libraries (leptonvideo SPI ${catkin_LIBRARIES})
4 |
--------------------------------------------------------------------------------
/lepton_camera/README.md:
--------------------------------------------------------------------------------
1 | # Video stream
2 | This interfaces reads out the VoSPIStream from the lepton camera. Details of the data transfer can be found in FLIR_Lepton_Data_Brief.pdf.
3 |
--------------------------------------------------------------------------------
/I2C_Lepton/FLIR_Lepton_Software_Interface_Description_Document_110_0144_03.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PX4/Lepton/HEAD/I2C_Lepton/FLIR_Lepton_Software_Interface_Description_Document_110_0144_03.pdf
--------------------------------------------------------------------------------
/lepton_camera/src/SPI/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Include directory for header file
4 | find_path(SPI_INCLUDE SPI.h ./)
5 | include_directories(${SPI_INCLUDE})
6 |
7 | #Add SPI library
8 | add_library (SPI SPI.cpp)
9 | target_include_directories (SPI PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
10 |
--------------------------------------------------------------------------------
/I2C_Lepton/README.md:
--------------------------------------------------------------------------------
1 | # I2C_Lepton
2 | I2C interface for Lepton Camera. This interface is based on the software interface description delivered by FLIR (FLIR_Lepton_Software_Interface_Description_Document_110_0144_03.pdf). The I2C interfaces works. However not all possible commands have been implemented. Also the application does not deliver a userfriendly readout of the data yet.
3 |
--------------------------------------------------------------------------------
/lepton_camera/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | lepton_camera
4 | 0.1.0
5 | The lepton package
6 | Chao Qu
7 |
8 | BSD
9 |
10 | catkin
11 |
12 | roscpp
13 | nodelet
14 | message_generation
15 | message_runtime
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/lepton_camera/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.3)
2 | project(lepton_camera)
3 |
4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
5 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
6 |
7 | find_package(catkin REQUIRED COMPONENTS
8 | roscpp nodelet
9 | message_generation
10 | )
11 | find_package(Boost COMPONENTS program_options REQUIRED)
12 |
13 |
14 |
15 |
16 | catkin_package(
17 | # INCLUDE_DIRS include
18 | # LIBRARIES bluefox2
19 | CATKIN_DEPENDS message_runtime
20 | # DEPENDS system_lib
21 | )
22 |
23 | include_directories(
24 | include
25 | ${catkin_INCLUDE_DIRS}
26 | )
27 |
28 | add_subdirectory(src/video)
29 | add_subdirectory(src/SPI)
30 |
31 | # dependencies
32 | add_dependencies(
33 | ${catkin_EXPORTED_TARGETS}
34 | ${PROJECT_NAME}_gencfg
35 | ${PROJECT_NAME}_gencpp
36 | ${${PROJECT_NAME}_EXPORTED_TARGETS}
37 | )
38 |
39 |
--------------------------------------------------------------------------------
/lepton_camera/src/SPI/SPI.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SPI testing utility (using spidev driver)
3 | *
4 | * Copyright (c) 2007 MontaVista Software, Inc.
5 | * Copyright (c) 2007 Anton Vorontsov
6 | *
7 | * This program is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation; either version 2 of the License.
10 | *
11 | * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
12 | */
13 |
14 | #ifndef SPI_H
15 | #define SPI_H
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | extern int spi_cs0_fd;
29 | extern int spi_cs1_fd;
30 | extern unsigned char spi_mode;
31 | extern unsigned char spi_bitsPerWord;
32 | extern unsigned int spi_speed;
33 | extern unsigned int spi_delay;
34 |
35 | int SpiOpenPort(int spi_device);
36 | int SpiClosePort(int spi_device);
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/I2C_Lepton/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "I2C_Interface.h"
3 | #include
4 |
5 |
6 | unsigned char buf_out[100]; // output from master
7 | unsigned char buf_in[100];// input for master from slave
8 | unsigned char data_out[100]; // data to be transferred from master to slave
9 | const char i2c_name[40] = "/dev/i2c-1";
10 | const int adress_lepton = 0x2A;
11 |
12 | int main() {
13 |
14 | unsigned short CommandID;
15 | unsigned short CommandWordLength;// number of words that are transferred
16 | unsigned short CommandType; // (Get=0; Set=1; Run=2)
17 |
18 | // Read in desired I2C command from user over command prompt
19 | int CommandIdx;
20 | CommandIdx=ReadI2CCommand();
21 | CommandID=commandList[CommandIdx][0];
22 | CommandWordLength=commandList[CommandIdx][1];
23 | CommandType=commandList[CommandIdx][2];
24 |
25 | unsigned short CommandByteLength=CommandWordLength<<1; // number of bytes that are transferred
26 |
27 |
28 |
29 | // Establish I2C bus to Lepton camera
30 | file = i2c_init(i2c_name, adress_lepton);
31 |
32 | // Execute desired Command
33 | WriteToCommandReg(CommandID,CommandWordLength,CommandType);
34 |
35 | // Read data from data register in master input buffer
36 | ReadDataReg(CommandByteLength);
37 |
38 | // Display content in master input buffer
39 | ReadOut(CommandByteLength);
40 |
41 | // Close I2C bus to Lepton camera
42 | i2c_close();
43 |
44 | return 0;
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/I2C_Lepton/I2C_Interface.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef I2C_INTERFACE
3 | #define I2C_INTERFACE
4 |
5 | extern int ak; // acknowledged integer
6 | extern unsigned char buf_out[100]; // output from master
7 | extern unsigned char buf_in[100];// input for master from slave
8 | extern unsigned char data_out[100]; //data that is transferred from master to slave
9 | extern int file; // file descriptor for lepton camera
10 | extern const int adress_lepton;
11 | extern const char i2c_name[40];
12 |
13 | /* Commands
14 | ***************
15 | Total number of known commands is saved in "n_commands"
16 | Commands are saved in two dimensional array "commandList":
17 | First column: command ID
18 | Second column: number of words transmitted
19 | Third column: type of command (Get=0; Set=1; Run=2)
20 | */
21 | extern const int n_commands;
22 | extern unsigned short commandList[19][3];
23 |
24 | // Functions
25 | extern int i2c_init(const char *filename, int addr);
26 | extern void i2c_close();
27 | extern void i2c_read(int n_in, int n_out);
28 | extern void WriteToCommandReg(unsigned short CommandID, unsigned short CommandDataLength, unsigned short CommandIdx);
29 | extern void WriteToDatalenghtReg(unsigned short DataLength);
30 | extern void WriteToDataReg(unsigned short n_words);
31 | extern void WaitingTillAccomplished();
32 | extern void ReadDataReg(unsigned short n_read);
33 | extern void ReadOut(unsigned short n_read);
34 | extern int ReadI2CCommand();
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/lepton_camera/src/SPI/SPI.cpp:
--------------------------------------------------------------------------------
1 | #include "SPI.h"
2 |
3 | int spi_cs0_fd = -1;
4 |
5 | unsigned char spi_mode = SPI_MODE_3;
6 | unsigned char spi_bitsPerWord = 8;
7 | unsigned int spi_speed = 2000000;
8 | unsigned int spi_delay = 0;
9 |
10 | int SpiOpenPort(int spi_device) {
11 | int status_value = -1;
12 | int *spi_cs_fd;
13 |
14 | //----- SET SPI MODE -----
15 | //SPI_MODE_0 (0,0) CPOL=0 (Clock Idle low level), CPHA=0 (SDO transmit/change edge active to idle)
16 | //SPI_MODE_1 (0,1) CPOL=0 (Clock Idle low level), CPHA=1 (SDO transmit/change edge idle to active)
17 | //SPI_MODE_2 (1,0) CPOL=1 (Clock Idle high level), CPHA=0 (SDO transmit/change edge active to idle)
18 | //SPI_MODE_3 (1,1) CPOL=1 (Clock Idle high level), CPHA=1 (SDO transmit/change edge idle to active)
19 | spi_mode = SPI_MODE_3;
20 |
21 | //----- SET BITS PER WORD -----
22 | spi_bitsPerWord = 8;
23 |
24 | //----- SET SPI BUS SPEED -----
25 | spi_speed = 20000000; //1000000 = 1MHz (1uS per bit)
26 |
27 | spi_cs_fd = &spi_cs0_fd;
28 |
29 | *spi_cs_fd = open(std::string("/dev/spidev0.0").c_str(), O_RDWR);
30 |
31 | if (*spi_cs_fd < 0) {
32 | perror("Error - Could not open SPI device");
33 | exit(1);
34 | }
35 |
36 | status_value = ioctl(*spi_cs_fd, SPI_IOC_WR_MODE, &spi_mode);
37 | if (status_value < 0) {
38 | perror("Could not set SPIMode (WR)...ioctl fail");
39 | exit(1);
40 | }
41 |
42 | status_value = ioctl(*spi_cs_fd, SPI_IOC_RD_MODE, &spi_mode);
43 | if (status_value < 0) {
44 | perror("Could not set SPIMode (RD)...ioctl fail");
45 | exit(1);
46 | }
47 |
48 | status_value = ioctl(*spi_cs_fd, SPI_IOC_WR_BITS_PER_WORD,
49 | &spi_bitsPerWord);
50 | if (status_value < 0) {
51 | perror("Could not set SPI bitsPerWord (WR)...ioctl fail");
52 | exit(1);
53 | }
54 |
55 | status_value = ioctl(*spi_cs_fd, SPI_IOC_RD_BITS_PER_WORD,
56 | &spi_bitsPerWord);
57 | if (status_value < 0) {
58 | perror("Could not set SPI bitsPerWord(RD)...ioctl fail");
59 | exit(1);
60 | }
61 |
62 | status_value = ioctl(*spi_cs_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
63 | if (status_value < 0) {
64 | perror("Could not set SPI speed (WR)...ioctl fail");
65 | exit(1);
66 | }
67 |
68 | status_value = ioctl(*spi_cs_fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_speed);
69 | if (status_value < 0) {
70 | perror("Could not set SPI speed (RD)...ioctl fail");
71 | exit(1);
72 | }
73 | return (status_value);
74 | }
75 |
76 | int SpiClosePort(int spi_device) {
77 | int status_value = -1;
78 | int *spi_cs_fd;
79 |
80 |
81 | spi_cs_fd = &spi_cs0_fd;
82 |
83 | status_value = close(*spi_cs_fd);
84 | if (status_value < 0) {
85 | perror("Error - Could not close SPI device");
86 | exit(1);
87 | }
88 | return (status_value);
89 | }
90 |
--------------------------------------------------------------------------------
/I2C_Lepton/I2C_Interface.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "I2C_Interface.h"
12 |
13 | int ak; // acknowledge integer
14 | int file; // file descriptor for lepton camera
15 |
16 | unsigned short commandList[19][3]={
17 | {(unsigned short)0x0100,2,0}, // Get AGC Enable State
18 | {(unsigned short)0x0101,2,1}, // Set AGC Enable State (1.Word:{0,1,2}; 2.Word:0)
19 | {(unsigned short)0x0124,1,0}, // Get AGC HEQ Damping factor
20 | {(unsigned short)0x0125,1,1}, // Set AGC HEQ Damping factor
21 | {(unsigned short)0x012C,1,0}, // Get AGC HEQ Clip Limit High
22 | {(unsigned short)0x012D,1,1}, // Set AGC HEQ Clip Limit High (1.Word:[0,4800])
23 | {(unsigned short)0x0144,2,0}, // Get AGC HEQ Output Scale Factor
24 | {(unsigned short)0x0145,2,1}, // Set AGC HEQ Output Scale Factor (1.Word:{0,1}; 2.Word:0)
25 | {(unsigned short)0x0148,2,0}, // Get AGC Calculation enable state
26 | {(unsigned short)0x0149,2,1}, // Set AGC Calculation enable state (1.Word:{0,1,2}; 2.Word:0)
27 | {(unsigned short)0x0208,4,0},
28 | {(unsigned short)0x0210,1,0},
29 | {(unsigned short)0x2014,1,0},
30 | {(unsigned short)0x0218,2,0}, // Get SYS Telemetry state
31 | {(unsigned short)0x0219,2,1}, // Set SYS Telemetry state (1.Word:{0,1,2}; 2.Word:0)
32 | {(unsigned short)0x021C,2,0},// Get SYS Telemetry location
33 | {(unsigned short)0x021D,2,1},// Set SYS Telemetry location (1.Word:{0,1,2}; 2.Word:0)
34 | {(unsigned short)0x0324,2,0}, // Get Video Freeze Enable State
35 | {(unsigned short)0x0325,2,1} // Set Video Freeze Enable State (1.Word:{0,1,2}; 2.Word:0)
36 | };
37 | const int n_commands=19;
38 |
39 | int i2c_init(const char *filename, const int addr) {
40 |
41 | // Check I2C connectivity
42 | file = open(filename, O_RDWR);
43 | if (file < 0) {
44 | printf("Failed to open bus\n");
45 |
46 | }
47 |
48 | // Check connectivity to lepton camera
49 | ak = ioctl(file, I2C_SLAVE, addr);
50 | if (ak < 0) {
51 | printf("Failed to acquire bus access and/or talk to slave\n");
52 | }
53 | return file;
54 | }
55 | void i2c_close(){
56 | // closes I2C connection
57 | close(file);
58 | return;
59 | }
60 |
61 |
62 | void i2c_read(int n_in, int n_out) {
63 |
64 | // Setting pointer to desired register address
65 | ak = write(file, buf_out, n_out);
66 |
67 | if (ak != n_out) {
68 | printf("Failed to access desired register\n");
69 | }
70 |
71 | // Reading in content of desired register and saving it in master input buffer
72 | ak = read(file, buf_in, n_in);
73 | if (ak != n_in) {
74 | printf("Could not read content in status register\n");
75 | }
76 |
77 | }
78 |
79 | void WriteToCommandReg( unsigned short CommandID, unsigned short CommandDataLength, unsigned short CommandType) {
80 |
81 | // Write data to data register if it is a set command
82 | if(CommandType==1){
83 | WriteToDataReg(CommandDataLength);
84 | }
85 |
86 | // Write to Data length register
87 | WriteToDatalenghtReg(CommandDataLength);
88 |
89 | // Write command into master output buffer
90 | buf_out[0] = 0x00;
91 | buf_out[1] = 0x04;
92 | buf_out[2]=(CommandID>>8)&0xFF;
93 | buf_out[3]=CommandID&0xFF;
94 |
95 | // Write command into command register
96 | ak = write(file, buf_out, 4);
97 | if (ak != 4) {
98 | printf("Error writing %i bytes\n", 4);
99 | }
100 | // Wait until execution of command is accomplished
101 | WaitingTillAccomplished();
102 |
103 | return;
104 |
105 | }
106 |
107 | void WriteToDataReg(unsigned short n_words){
108 |
109 | // Write n_words data into master output buffer
110 | buf_out[0] = 0x00;
111 | buf_out[1] = 0x08;
112 |
113 | for(int j=0;j>8)&0xFF;;
133 | buf_out[3] = DataLength&0xFF;
134 |
135 |
136 | // Write data length into data length register
137 | ak = write(file, buf_out, 4);
138 |
139 | if (ak != 4) {
140 | printf("Error writing %i bytes to data length register\n", 4);
141 | }
142 | return;
143 |
144 | }
145 |
146 |
147 | void ReadDataReg(unsigned short n_read){
148 |
149 | // Write address of data register into master output buffer
150 | buf_out[0]=0x00;
151 | buf_out[1]=0x08;
152 |
153 | // reads n_read bytes from data register and saves it in master input buffer
154 | i2c_read(n_read,2);
155 |
156 | return;
157 | }
158 |
159 | void ReadOut(unsigned short n_read) {
160 | short output_int=0;
161 |
162 | // Reads out n_out bytes content of master input buffer in hexadecimal format
163 | printf("Master Input buffer\n");
164 | printf("*******************\n");
165 | for (unsigned short i = 0; i < n_read; i++) {
166 |
167 | printf("%d. byte:0x%0*x\n", i + 1, 2, buf_in[i]);
168 | }
169 | printf("Total in hexadecimal format: 0x");
170 | for (unsigned short i = 0; i < n_read; i++) {
171 |
172 |
173 | }
174 | printf("\n");
175 | for (unsigned short i = 0; i < n_read/2; i++) {
176 | for (unsigned short j=0;j<2;j++){
177 | output_int=(((short)buf_in[i+j])<<8*(1-j))+output_int;
178 |
179 | }
180 | printf("%d. word: %d\n",i+1,output_int);
181 | output_int=0;
182 | }
183 | printf("\n\n");
184 | return;
185 | }
186 |
187 |
188 | int ReadI2CCommand(){
189 | int temp;
190 | // Read in input command
191 | printf("Please enter command in hexadecimal format : ");
192 | scanf("%x", &temp);
193 |
194 | // Check whether command is valid
195 | int i;
196 | int j;
197 | for(i=0;i>8)&0xFF;
221 | data_out[j*2+1]=((unsigned short)temp)&0xFF;
222 | }
223 | }
224 | printf("\n");
225 | return i;
226 | }
227 | }
228 |
229 |
230 |
231 | void WaitingTillAccomplished(){
232 |
233 | // Checks BUSY bit of status register and returns when cleared
234 |
235 | buf_out[0]=0x00;
236 | buf_out[1]=0x02;
237 | i2c_read(2,2);
238 |
239 | while(buf_in[1] & 1) {
240 | printf("Waiting for command to be accomplished\n");
241 | i2c_read(2,2);
242 | }
243 |
244 | // Sanity check
245 | printf("Status register\n");
246 | printf("***************\n");
247 | printf("Error Code: %d\n", (int)buf_in[0]);
248 | printf("second byte:0x%0*x\n", 2, buf_in[1]);
249 | printf("\n");
250 | return;
251 | }
252 |
253 |
254 |
--------------------------------------------------------------------------------
/lepton_camera/src/video/lepton.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2014, Pure Engineering LLC
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | * Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include "ros/ros.h"
38 | #include "ros/time.h"
39 | #include "std_msgs/String.h"
40 | #include "std_msgs/MultiArrayLayout.h"
41 | #include "std_msgs/MultiArrayDimension.h"
42 | #include "std_msgs/Int32MultiArray.h"
43 | #include "sensor_msgs/Image.h"
44 | #include "SPI.h"
45 |
46 | #include
47 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
48 |
49 | static void pabort(const char *s) {
50 | perror(s);
51 | abort();
52 | }
53 |
54 | #define VOSPI_FRAME_SIZE (164)
55 | uint8_t lepton_frame_packet[VOSPI_FRAME_SIZE];
56 | static unsigned int lepton_image[80][80] = { 0 };
57 | ros::Time capture_time;
58 |
59 |
60 |
61 | void resync() {
62 | // This function tries to resynchronize the video stream
63 |
64 | // Close SPI Port
65 | SpiClosePort(0);
66 |
67 | // Sleep for 0.75 second to trigger resynch.
68 | printf("Synchronizing video stream...\n");
69 | usleep(750000);
70 |
71 | // Open Port again
72 | SpiOpenPort(0);
73 |
74 | return;
75 |
76 | }
77 |
78 | void reboot() {
79 | // This functions reboots lepton camera
80 |
81 | // Close SPI Port
82 | SpiClosePort(0);
83 |
84 | // Unplug power
85 | printf("Unplug power for 40 ms\n");
86 | system("gpio -g write 97 0");
87 | usleep(40000);
88 | system("gpio -g write 97 1");
89 |
90 | // Open SPI Port again
91 | SpiOpenPort(0);
92 |
93 | return;
94 |
95 | }
96 |
97 | int transfer(int fd, int current_frame) {
98 | int ret;
99 | int i;
100 | int packet_number;
101 | uint8_t tx[VOSPI_FRAME_SIZE] = { 0, };
102 |
103 |
104 | // Take capture time of image corresponding to first package
105 | if(current_frame==0){
106 | capture_time=ros::Time::now();
107 | }
108 |
109 | struct spi_ioc_transfer tr;
110 |
111 | tr.tx_buf = (unsigned long) tx;
112 | tr.rx_buf = (unsigned long) lepton_frame_packet;
113 | tr.len = VOSPI_FRAME_SIZE;
114 | tr.delay_usecs = spi_delay;
115 | tr.speed_hz = spi_speed;
116 | tr.bits_per_word = spi_bitsPerWord;
117 |
118 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
119 |
120 | if (ret < 1)
121 | pabort("can't send spi message");
122 |
123 | if (((lepton_frame_packet[0] & 0xf) != 0x0f)) {
124 | packet_number = lepton_frame_packet[1];
125 |
126 | //printf("%d", packet_number);
127 |
128 | if (packet_number == current_frame) {
129 | for (i = 0; i < 80; i++) {
130 | lepton_image[packet_number][i] = (lepton_frame_packet[2 * i + 4]
131 | << 8 | lepton_frame_packet[2 * i + 5]);
132 | }
133 | } else {
134 | packet_number = -1;
135 | }
136 | }
137 | return packet_number;
138 | }
139 |
140 | sensor_msgs::Image normalize(sensor_msgs::Image I,
141 | unsigned int Data_raw[80][80]) {
142 |
143 | int i;
144 | int j;
145 | unsigned int maxval = 0;
146 | unsigned int minval = UINT_MAX;
147 |
148 | // Calculating extrema
149 | for (i = 0; i < 60; i++) {
150 | for (j = 0; j < 80; j++) {
151 | if (Data_raw[i][j] > maxval) {
152 | maxval = Data_raw[i][j];
153 | }
154 | if (Data_raw[i][j] < minval) {
155 | minval = Data_raw[i][j];
156 | }
157 | }
158 | }
159 | float diff = maxval - minval;
160 | if (diff == 0.0) {
161 | diff = 1.0;
162 | }
163 | float scale = 255 / diff;
164 |
165 | // File array with normalized pixel points
166 | for (i = 0; i < 80; i++) {
167 | for (j = 0; j < 60; j++) {
168 | I.data[j * 80 + i] = (Data_raw[j][i] - minval) * scale;
169 | }
170 | }
171 |
172 | return I;
173 | }
174 |
175 | sensor_msgs::Image agc(sensor_msgs::Image I,
176 | unsigned int Data_raw[80][80]) {
177 | int i;
178 | int j;
179 | // File array with normal
180 | for (i = 0; i < 80; i++) {
181 | for (j = 0; j < 60; j++) {
182 | I.data[j * 80 + i] = Data_raw[j][i];
183 | }
184 | }
185 |
186 | return I;
187 | }
188 |
189 |
190 | sensor_msgs::Image calib(sensor_msgs::Image I,
191 | unsigned int Data_raw[80][80], int threshold) {
192 |
193 | int i;
194 | int j;
195 | unsigned int maxval = 0;
196 | unsigned int minval = UINT_MAX;
197 |
198 | // Calculating extrema
199 | for (i = 0; i < 60; i++) {
200 | for (j = 0; j < 80; j++) {
201 | if (Data_raw[i][j] > maxval) {
202 | maxval = Data_raw[i][j];
203 | }
204 | if (Data_raw[i][j] < minval) {
205 | minval = Data_raw[i][j];
206 | }
207 | }
208 | }
209 | float diff = maxval - minval;
210 | if (diff == 0.0) {
211 | diff = 1.0;
212 | }
213 | float scale = 255 / diff;
214 |
215 | // File array with thresholded pixel points
216 | for (i = 0; i < 80; i++) {
217 | for (j = 0; j < 60; j++) {
218 | I.data[j * 80 + i] = (Data_raw[j][i] - minval) * scale;
219 | if (I.data[j * 80 + i] maxval) {
243 | maxval = Data_raw[i][j];
244 | }
245 | if (Data_raw[i][j] < minval) {
246 | minval = Data_raw[i][j];
247 | }
248 | }
249 | }
250 | float diff = maxval - minval;
251 | if (diff == 0.0) {
252 | diff = 1.0;
253 | }
254 | float scale = 255 / diff;
255 |
256 | // File array with normalized inverted pixel points
257 | for (i = 0; i < 80; i++) {
258 | for (j = 0; j < 60; j++) {
259 | I.data[j * 80 + i] = 255 - (Data_raw[j][i] - minval) * scale;
260 | }
261 | }
262 |
263 | return I;
264 | }
265 |
266 | int AskFormat() {
267 | int Videoformat;
268 | printf("Please enter video format? (Press 0 to list different formats)\n");
269 | scanf("%d", &Videoformat);
270 | if (Videoformat == 0) {
271 | printf("Available formats\n");
272 | printf("*****************\n");
273 | printf("1: Linear normalization (1 Pixel=8 Bit)\n");
274 | printf("2: AGC mode (1 Pixel=8 Bit)\n");
275 | printf("3: Calibration mode (1 Pixel=8 Bit)\n");
276 | printf("4: Inversion mode (1 Pixel=8 Bit)\n");
277 | exit(0);
278 | }
279 | return Videoformat;
280 |
281 | }
282 |
283 | int AskThreshold() {
284 | int temp;
285 | printf("Please define threshold value [0,255]\n");
286 | scanf("%d", &temp);
287 | return temp;
288 |
289 | }
290 |
291 |
292 |
293 |
294 |
295 | int main(int argc, char *argv[]) {
296 |
297 | // Ask user which mode video format shall be
298 | int format = AskFormat();
299 |
300 | // Optionaly ask user which threshold should be used
301 | int c_threshold;
302 | if (format == 3) {
303 | c_threshold = AskThreshold();
304 | }
305 |
306 | int i, j;
307 | int i_sync = 0;
308 | ros::init(argc, argv, "arrayPublisher");
309 | ros::NodeHandle n;
310 | ros::Publisher pub = n.advertise < std_msgs::Int32MultiArray
311 | > ("array", 100);
312 | ros::Publisher data = n.advertise < sensor_msgs::Image > ("IR_data", 100);
313 |
314 | sensor_msgs::Image IR_data;
315 | IR_data.height = 60;
316 | IR_data.width = 80;
317 | IR_data.step = 80;
318 | IR_data.encoding = "mono8";
319 | system("gpio -g write 97 1");
320 | int ret = 0;
321 | int reset = 0;
322 | while (ros::ok()) {
323 |
324 | IR_data.data.clear();
325 | for (j = 0; j < (int) IR_data.height; j++) {
326 | for (i = 0; i < (int) IR_data.width; i++) {
327 | IR_data.data.push_back(0);
328 | }
329 | }
330 | //open spi port
331 | SpiOpenPort(0);
332 |
333 | // Retrieving frame data
334 | reset = 0;
335 | for (j = 0; j < 60; j++) {
336 | j = transfer(spi_cs0_fd, j); // j:=Packet number
337 |
338 | if (j < 0 && j > -2) {
339 | reset += 1;
340 | usleep(1000);
341 |
342 | } else if (j < -2) {
343 | j = -1;
344 | }
345 |
346 | // Try to resynchronize video stream or reboot camera after 750 false packages
347 | // First try to resynchronize video stream.
348 | // After 3 failed attempts. -> Reboot camera
349 | if (reset == 750) {
350 |
351 | if (i_sync < 3) {
352 | resync();
353 | i_sync++;
354 | reset = 0;
355 | } else {
356 | reboot();
357 | i_sync = 0;
358 | reset = 0;
359 |
360 | }
361 | }
362 | }
363 |
364 | printf("\n");
365 |
366 | // Process raw data
367 | switch (format) {
368 | case 1: // linear normalization
369 | IR_data = normalize(IR_data, lepton_image);
370 | break;
371 | case 2: // AGC mode
372 | IR_data = agc(IR_data, lepton_image);
373 | break;
374 | case 3: // calib mode
375 | IR_data = calib(IR_data, lepton_image,c_threshold);
376 | break;
377 | case 4: // inversion mode
378 | IR_data = inversion(IR_data, lepton_image);
379 | break;
380 | default:
381 | printf("Unknown video data. Cannot process data\n");
382 | return 0;
383 |
384 | }
385 |
386 | // Publish data over ROS
387 |
388 | IR_data.header.stamp.sec=capture_time.sec;
389 | IR_data.header.stamp.nsec=capture_time.nsec;
390 | data.publish(IR_data);
391 | ROS_INFO("Successfully published IR image!");
392 |
393 | ros::spinOnce();
394 |
395 | SpiClosePort(0);
396 | //usleep(37038);
397 | }
398 |
399 | return ret;
400 | }
401 |
--------------------------------------------------------------------------------