---
# System prepended metadata

title: Node

---

## Node
execution unit, it mainly function is calculating, controling or connecting to other nodes.
>[!Warning] it is a temporary storage place

### python
#### 1. once
- hello.py
```python=
from rclpy import init, create_node, spin, shutdown

def main(args=None): #introduce arguments
    rclpy.init(args=args)   
    node = create_node("HELLO") #create a node HELLO
    node.get_logger().info("Hello, World!!!") # print
    spin(node) # run once
    shutdown()
if __name__ == '__main__':
    main()

```

#### 2. loop
- hello.py
```python=
from rclpy import init, spin_once, shutdown

def main(args=None): #introduce arguments
    init(args=args)   
    node = rclpy.create_node("HELLO") #create a node HELLO
    rate = node.create_rate(1) # set rate 1Hz
    
    while rclpy.ok(): # rclpy nor interrupt
        node.get_logger().info("Hello, World!!!") # print
        spin_once(node) # run once
    shutdown()
if __name__ == '__main__':
    main()

```

- package.xml 
```xml=
...
<exec_depend>rclpy</exec_depend>
...
```

###  C++
#### 1. once
- hello.cpp
```cpp=
#include "rclcpp/rclcpp.hpp"

int main(int argc, char** argv){
    rclcpp::init(argc, argv);
    
    auto node = rclcpp::Node::make_shared("HELLO");
    RCLCPP_INFO(node->get_logger(), "Hello, World!!!");
        
    rclcpp::spin(node)
    rclcpp::shutdown();
    return 0;
}
```

#### 2. loop
- ROS
```cpp=
#include "rclcpp/rclcpp.hpp"

int main(int argc, char ** argv){
    rclcpp::init(argc, argv);
    
    auto node = rclcpp::Node::make_shared("HELLO");
    rclcpp::WallRate loop_rate(1);
    while (rclcpp::ok()){
        rclcpp::spin_some(node);
        RCLCPP_INFO(node->get_logger(), "Hello, World!!!");
        loop_rate.sleep();
    }
    rclcpp::shutdown();
    return 0;
}
```

- ROS2 - 1
```cpp=
#include "rclcpp/rclcpp.hpp"
// #include <chrono>
using namespace std;

int main(int argc, char ** argv){
    rclcpp::init(argc, argv);
    
    auto node = rclcpp::Node::make_shared("HELLO");
    auto timer = node->create_wall_timer(
        1s, //chrono::seconds(1);
        [node]() -> void{RCLCPP_INFO(node->get_logger(), "Hello, World!!!");}
    );
    
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}
```
- ROS2 - 2
```cpp=
#include "rclcpp/rclcpp.hpp"
// #include <chrono>
using namespace std;

void callback(rclcpp::Node::SharedPtr node) {
    RCLCPP_INFO(node->get_logger(), "Hello World in Loop!");
}

int main(int argc, char ** argv){
    rclcpp::init(argc, argv);
    
    auto node = rclcpp::Node::make_shared("HELLO");
    auto timer = node->create_wall_timer(
        1s, //chrono::seconds(1);
        bind(&callback, node) //zero function --> callback(node)
    );
    
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}
```

> [!Tip] Zero function
calling function can't use paraments

## Node Attribute - Parameter
- intro 
1. it's not a message stream
2. it can use CLI to operate

> [!Warning] Parameter
> When you want to run parameter, needing to run Node first. 

### Python
```python=
from rclpy import init, spin
from rclpy.node import Node 
from rclpy.parameter import Parameter

class Para(Node):
    def __init__(self):
        super().__init__('param_node')
        self.declare_parameter('my_param', 'world') # create a parameter
        self.timer = self.create_timer(1, self.callback)

    def callback(self):
        my_param = self.get_parameter('my_param').get_parameter_value().string_value
        self.get_logger().info(f'Hello, {my_param}') # get parameter value and data-type change to string

        new_my_param = Parameter(
            'my_param',  #parameter name
            Parameter.Type.STRING, #parameter type
            'world' #parameter value
        )
        self.set_parameters([new_my_param]) # update parameter

def main():
    init()
    spin( Para() )

if __name__ == '__main__':
    main()
```
> `declare_parameter` 
> `get_parameter_value`
> `set_parameters`: 記得加***s***

- setup.py
```python=
entry_points={
    'console_scripts': [
        'param_node = py_param.node:main' 
    ],
},
```

### Cpp
```cpp=
#include <rclcpp/rclcpp.hpp>
#include <chrono>
#include <string>
#include <vector>
using namespace std::chrono_literals;

using rclcpp::Node;
using rclcpp::init;
using rclcpp::spin;
using rclcpp::Parameter;
using rclcpp::TimerBase;
using rclcpp::shutdown;
using std::string;
using std::vector;
using std::make_shared;

class Para: public Node { 
    public:
        Para(): Node("para_node") {
            this->declare_parameter("my_para", "world");
            
            timer_= this->create_wall_timer(
            1s, 
            [this](){
                string my_para = this->get_parameter("my_para").as_string();
                RCLCPP_INFO(this->get_logger(), "Hello, %s!", my_para.c_str());
                vector<Parameter> all_para{Parameter("my_para", "world")};
                this->set_parameters(all_para);
            });
        }

    private:
        TimerBase::SharedPtr timer_;       
};

int main(int args, char** argv){
    init(args, argv);
    spin( make_shared<Para>() );
    shutdown();
}
```

- CMakeLists.txt
```txt=
add_executable(para_node src/node.cpp)
ament_target_dependencies(para_node rclcpp)

install(TARGETS
    para_node
    DESTINATION lib/${PROJECT_NAME}
)
```

### Linux
```bash=
ros2 param set <node_name> <para_name> <changed_value>
```

### Parameter Function - launch
