Skip to content

Commit 8a41f4b

Browse files
authored
Merge pull request #177 from pockerman/feat/174-add-diff-drive-robot-model
Feat/174 add diff drive robot model
2 parents f7f1c0d + c82e9e4 commit 8a41f4b

11 files changed

Lines changed: 825 additions & 158 deletions

File tree

config.h.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/*Use Webots*/
1717
#cmakedefine BITRL_WEBOTS
1818

19-
/*Use Chron*/
19+
/*Use Chrono*/
2020
#cmakedefine BITRL_CHRONO
2121

2222
/*Use OpenCV*/

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ADD_SUBDIRECTORY(example_2)
2929
ADD_SUBDIRECTORY(example_3)
3030
ADD_SUBDIRECTORY(example_4)
3131
ADD_SUBDIRECTORY(example_5)
32+
ADD_SUBDIRECTORY(example_6)
3233
ADD_SUBDIRECTORY(example_7)
3334
ADD_SUBDIRECTORY(example_8)
3435
ADD_SUBDIRECTORY(example_9)

examples/example_11/example_11.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
The <a href="https://github.com/projectchrono/chrono">Chrono</a> library is the main library that _bitrl_ is using in order
44
to simulate robots and create environments for reinforcement learning agents. As such, knowing your way around
55
Chrono is essential. However, Chrono is a relatively large library with many components and therefore not necessarily easy
6-
to grasp. In a series of examples, we will see main components of the library that _bitrl_ utilizes.
6+
to grasp. In a series of examples, we will see the main components of the library that _bitrl_ utilizes.
77
Note that you should have compiled Chrono with <a href="https://irrlicht.sourceforge.io/">Irrlicht</a> support in order to be able to run this example.
88

99
The main interface for creating rigid bodies in Chrono is the <a href="https://api.projectchrono.org/9.0.0/classchrono_1_1_ch_body.html">ChBody</a>
1010
class. You can also find this <a href="https://api.projectchrono.org/9.0.0/rigid_bodies.html"> Rigid Bodies</a> helpful.
11-
_ChBody_ is an abstract class, and therefore we cannot instantiate it directly. Chrono provides various classes however we can
11+
_ChBody_ is an abstract class, and therefore we cannot instantiate it directly. Chrono provides various classes however, we can
1212
immediately use. The one we will use in this example is the _ChBodyEasyBox_ class. This is defined in the _chrono/physics/ChBodyEasy.h_ header.
13-
Let's first create a box and try to visualize it. Below is the function that constructs a box.
13+
Let's first create a box and try to visualize it. The function below does exactly that.
1414

1515
@code{.cpp}
1616
std::shared_ptr<chrono::ChBody> create_box(real_t xlength, real_t ylength, real_t zlength,
@@ -30,12 +30,14 @@ real_t density, bool create_visualization)
3030
@endcode
3131

3232

33-
The following is a helper for setting up the visualization
33+
The following is a helper for setting up the visualization. We need to build Chrono with Irrlicht support in order to be able to
34+
use it as a visualization engine. You can find more information about the
35+
visualisation system in Chrono at <a href="https://api.projectchrono.org/9.0.0/visualization_system.html">Visualization System</a>.
3436

3537
@code{.cpp}
3638
void prepare_visualization(chrono::irrlicht::ChVisualSystemIrrlicht& visual)
3739
{
38-
visual.SetWindowSize(WINDOW_WIDTH, WINDOW_WIDTH); //WINDOW_HEIGHT);
40+
visual.SetWindowSize(WINDOW_WIDTH, WINDOW_WIDTH);
3941
visual.SetWindowTitle(WINDOW_TITLE);
4042
visual.Initialize();
4143

@@ -47,8 +49,9 @@ visual.Initialize();
4749
}
4850
@endcode
4951

50-
Below is the main function:
51-
52+
Below is the main driver for this example.
53+
It creates a box and attaches it to a _ChSystem_ (see <a href="https://api.projectchrono.org/9.0.0/simulation_system.html">Simulation system</a> for more information).
54+
It also sets up a minimal visualization obejct _ChVisualSystemIrrlicht_ for the simulation and finally runs the simulation loop.
5255
@code{.cpp}
5356
int main()
5457
{

examples/example_12/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ ADD_EXECUTABLE(${EXECUTABLE} ${SOURCE})
88
TARGET_LINK_LIBRARIES(${EXECUTABLE} PRIVATE bitrllib pthread boost_log)
99

1010
IF(ENABLE_CHRONO)
11-
TARGET_LINK_LIBRARIES(${EXECUTABLE} PRIVATE Chrono::Chrono_core)
11+
TARGET_LINK_LIBRARIES(${EXECUTABLE} PRIVATE Chrono::Chrono_core Chrono::Chrono_irrlicht)
1212
ENDIF ()
1313

1414

examples/example_12/example_12.cpp

Lines changed: 208 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,235 @@
1-
/**
2-
* This example utilises the ```TensorboardServer``` class to log values of interest when running
3-
* an experiment. We can monitor the experimet using <a
4-
*href="https://www.tensorflow.org/tensorboard">tensorboard</a>. The ```TensorboardServer``` class
5-
*is a simple wrapper that exposes three functions
6-
*
7-
* - ```add_scalar```
8-
* - ```add_scalars```
9-
* - ```add_text```
10-
*
11-
* We will use ```add_scalar``` and ```add_text```. In order to run this example, fire up the
12-
*server using the ```torchboard_server/start_uvicorn.sh```. The server listens at port 8002. You
13-
*can change this however you want just make sure that the port is not used and also update the
14-
* variable ```TORCH_SERVER_HOST``` in the code below accordingly. Note that the implementation
15-
*uses <a
16-
*href="https://pytorch.org/docs/stable/_modules/torch/utils/tensorboard/writer.html#SummaryWriter">SummaryWriter</a>
17-
*class. Thus you will need to have PyTorch installed on the machine that you run the server.
18-
*/
1+
#include "bitrl/bitrl_config.h"
2+
3+
#ifdef BITRL_CHRONO
194

205
#include "bitrl/bitrl_types.h"
21-
#include "bitrl/utils/io/json_file_reader.h"
22-
#include "bitrl/network/tensorboard_server.h"
6+
#include "bitrl/bitrl_consts.h"
237

24-
#include <filesystem>
25-
#include <iostream>
26-
#include <random>
27-
#include <string>
8+
#ifdef BITRL_LOG
9+
#define BOOST_LOG_DYN_LINK
10+
#include <boost/log/trivial.hpp>
11+
#endif
12+
13+
#include <chrono/physics/ChSystemNSC.h>
14+
#include <chrono/physics/ChBodyEasy.h>
15+
#include "chrono/assets/ChVisualSystem.h"
16+
#include <chrono_irrlicht/ChVisualSystemIrrlicht.h>
17+
18+
#include <chrono/physics/ChLinkMotorRotationSpeed.h>
19+
#include <chrono/functions/ChFunctionConst.h>
20+
21+
#include <memory>
2822

2923
namespace example_12
3024
{
25+
26+
using namespace chrono;
27+
using namespace chrono::irrlicht;
3128
using namespace bitrl;
32-
using utils::io::JSONFileReader;
33-
using network::TensorboardServer;
3429

35-
namespace fs = std::filesystem;
36-
const std::string CONFIG = "config.json";
30+
const real_t WHEEL_RADIUS = 0.1;
31+
const real_t CHASSIS_HEIGHT = 0.1;
32+
const real_t WHEEL_WIDTH = 0.05;
33+
const real_t CASTER_RADIUS = 0.05;
34+
35+
void draw_world_axes(chrono::irrlicht::ChVisualSystemIrrlicht& vis,
36+
real_t scale = 1.0) {
37+
auto* driver = vis.GetVideoDriver();
38+
39+
// X axis (red)
40+
driver->draw3DLine(
41+
{0, 0, 0},
42+
{static_cast<float>(scale), 0, 0},
43+
irr::video::SColor(255, 255, 0, 0));
44+
45+
// Y axis (green)
46+
driver->draw3DLine(
47+
{0, 0, 0},
48+
{0, static_cast<float>(scale), 0},
49+
irr::video::SColor(255, 0, 255, 0));
50+
51+
// Z axis (blue)
52+
driver->draw3DLine(
53+
{0, 0, 0},
54+
{0, 0, static_cast<float>(scale)},
55+
irr::video::SColor(255, 0, 0, 255));
56+
}
57+
58+
auto build_generic_material()
59+
{
60+
auto material = chrono_types::make_shared<ChContactMaterialNSC>();
61+
material->SetFriction(0.8f);
62+
material->SetRestitution(0.1f);
63+
return material;
64+
}
3765

38-
} // namespace example_12
66+
auto build_floor(std::shared_ptr<ChContactMaterialNSC> material)
67+
{
68+
auto floor = chrono_types::make_shared<chrono::ChBodyEasyBox>(
69+
5, 5, 0.1, // size
70+
1000, // density
71+
true, true, material); // visual + collision
72+
73+
floor->SetPos(chrono::ChVector3d(0,0,-0.05));
74+
floor->SetFixed(true);
75+
floor->EnableCollision(true);
76+
return floor;
77+
}
3978

40-
int main()
79+
auto build_chassis(std::shared_ptr<ChContactMaterialNSC> material)
4180
{
81+
auto chassis = chrono_types::make_shared<ChBodyEasyBox>(
82+
0.5, 0.3, CHASSIS_HEIGHT,
83+
1000,
84+
true, true, material);
85+
86+
chrono::ChVector3d pos(0.0, 0.0, WHEEL_RADIUS + CHASSIS_HEIGHT/2.0 + 0.01);
87+
chassis->SetPos(pos);
88+
89+
chrono::ChVector3d vel(0.5, 0.0, 0.0);
90+
chassis->SetPosDt(vel);
91+
chassis->EnableCollision(true);
92+
return chassis;
93+
}
4294

43-
using namespace example_12;
95+
auto build_wheel(std::shared_ptr<ChContactMaterialNSC> material, const chrono::ChVector3d& pos)
96+
{
97+
auto wheel = chrono_types::make_shared<chrono::ChBodyEasyCylinder>(
98+
chrono::ChAxis::Y,
99+
WHEEL_RADIUS,
100+
WHEEL_WIDTH,
101+
1000,
102+
true, true, material);
103+
104+
wheel->SetPos(pos);
105+
wheel->EnableCollision(true);
106+
return wheel;
107+
}
44108

45-
try
46-
{
109+
auto build_motor(std::shared_ptr<ChBodyEasyCylinder> wheel,
110+
std::shared_ptr<ChBodyEasyBox> chassis,
111+
std::shared_ptr<ChFunctionConst> speed_func,
112+
const chrono::ChVector3d& pos)
113+
{
114+
auto motor = chrono_types::make_shared<chrono::ChLinkMotorRotationSpeed>();
47115

48-
// load the json configuration
49-
JSONFileReader json_reader(CONFIG);
50-
json_reader.open();
116+
chrono::ChQuaternion<> rot = chrono::QuatFromAngleX(chrono::CH_PI_2);
117+
motor->Initialize(
118+
wheel,
119+
chassis,
120+
chrono::ChFrame<>(pos, rot)
121+
);
51122

52-
auto experiment_dict = json_reader.template get_value<std::string>("experiment_dict");
53-
auto experiment_id = json_reader.template get_value<std::string>("experiment_id");
123+
motor->SetSpeedFunction(speed_func);
124+
return motor;
125+
}
54126

55-
std::cout << "Experiment directory: " << experiment_dict << std::endl;
56-
std::cout << "Experiment id: " << experiment_id << std::endl << std::endl;
127+
auto build_caster_wheel(std::shared_ptr<ChContactMaterialNSC> material)
128+
{
57129

58-
const fs::path EXPERIMENT_DIR_PATH = experiment_dict + experiment_id;
130+
auto caster = chrono_types::make_shared<ChBodyEasySphere>(
131+
CASTER_RADIUS, // radius
132+
1000, // density
133+
true, // visualization
134+
true, // collision
135+
material);
59136

60-
// the first thing we want to do when monitoring experiments
61-
// is to create a directory where all data will reside
62-
std::filesystem::create_directories(experiment_dict + experiment_id);
137+
caster->SetPos(chrono::ChVector3d(0.2, 0, 0.05));
138+
caster->EnableCollision(true);
139+
return caster;
140+
}
63141

64-
const auto input_size = json_reader.template get_value<uint_t>("input_size");
65-
const auto output_size = json_reader.template get_value<uint_t>("output_size");
66-
const auto num_epochs = json_reader.template get_value<uint_t>("num_epochs");
67-
const auto learning_rate = json_reader.template get_value<real_t>("lr");
68-
auto log_path = json_reader.template get_value<std::string>("log_path");
142+
auto build_caster_joint(std::shared_ptr<ChBodyEasySphere> caster,
143+
std::shared_ptr<ChBodyEasyBox> chassis)
144+
{
145+
auto caster_joint = chrono_types::make_shared<ChLinkLockRevolute>();
69146

70-
// log the hyperparameters
71-
std::cout << "Input size: " << input_size << std::endl;
72-
std::cout << "Output size: " << output_size << std::endl;
73-
std::cout << "Max epochs: " << num_epochs << std::endl;
74-
std::cout << "Learning rate: " << learning_rate << std::endl;
147+
caster_joint->Initialize(
148+
caster,
149+
chassis,
150+
ChFrame<>(chrono::ChVector3d(-0.25, 0, CASTER_RADIUS), QUNIT));
151+
return caster_joint;
75152

76-
TensorboardServer logger("http://0.0.0.0:8002");
153+
}
154+
}
77155

78-
std::cout << "Logging results at " << logger.get_log_dir_path() << std::endl;
79-
logger.init(log_path);
156+
int main() {
80157

81-
logger.add_scalar("lr", learning_rate);
82-
logger.add_scalar("seed", 42);
83-
logger.add_scalar("num_epochs", num_epochs);
84-
logger.add_text("optimizer", "torch::optim::SGD");
85-
logger.close();
86-
}
87-
catch (std::exception &e)
88-
{
89-
std::cout << e.what() << std::endl;
90-
}
91-
catch (...)
92-
{
93-
std::cout << "Unknown exception occured" << std::endl;
158+
using namespace example_12;
159+
ChSystemNSC system;
160+
system.SetGravitationalAcceleration(chrono::ChVector3d(0,0,-bitrl::consts::maths::G));
161+
system.SetCollisionSystemType(chrono::ChCollisionSystem::Type::BULLET);
162+
163+
// create a generic material to use
164+
auto material = example_12::build_generic_material();
165+
166+
// build floor
167+
auto floor = example_12::build_floor(material);
168+
system.Add(floor);
169+
170+
// build chassis
171+
auto chassis = example_12::build_chassis(material);
172+
system.Add(chassis);
173+
174+
// build wheels
175+
auto left_wheel = example_12::build_wheel(material,chrono::ChVector3d(0, 0.2, 0.1));
176+
auto right_wheel = example_12::build_wheel(material,chrono::ChVector3d(0,-0.2, 0.1));
177+
system.Add(left_wheel);
178+
system.Add(right_wheel);
179+
180+
// build motor
181+
auto motor_left = example_12::build_motor(left_wheel, chassis,
182+
chrono_types::make_shared<chrono::ChFunctionConst>(-4.5), chrono::ChVector3d(0,0.2,0.1));
183+
auto motor_right = build_motor(right_wheel, chassis,
184+
chrono_types::make_shared<chrono::ChFunctionConst>(-4.5), chrono::ChVector3d(0,-0.2,0.1));
185+
186+
system.Add(motor_left);
187+
system.Add(motor_right);
188+
189+
auto caster = example_12::build_caster_wheel(material);
190+
system.Add(caster);
191+
192+
auto caster_joint = example_12::build_caster_joint(caster, chassis);
193+
system.Add(caster_joint);
194+
195+
// create the visualization system
196+
chrono::irrlicht::ChVisualSystemIrrlicht vis;
197+
198+
vis.AttachSystem(&system);
199+
vis.SetWindowSize(1280,720);
200+
vis.SetWindowTitle("Example 12 Differential Drive Robot");
201+
vis.Initialize();
202+
vis.AddSkyBox();
203+
vis.AddLogo();
204+
vis.AddSkyBox();
205+
vis.AddCamera({0, -2, 1}, {0, 0, 0});
206+
vis.AddTypicalLights();
207+
vis.BindAll();
208+
209+
real_t step_size = 0.002;
210+
while (vis.Run()) {
211+
212+
vis.BeginScene();
213+
vis.Render();
214+
draw_world_axes(vis, 2.0);
215+
216+
auto position = chassis -> GetPos();
217+
std::cout << position <<std::endl;
218+
219+
system.DoStepDynamics(step_size);
220+
vis.EndScene();
94221
}
95222

96223
return 0;
97224
}
225+
#else
226+
#include <iostream>
227+
int main()
228+
{
229+
std::cerr<<"You need PROJECTCHRONO configured with "
230+
<<"bitrl in order to run this example "
231+
<<"Reconfigure bitrl and set ENABLE_CHRONO=ON"<<std::endl;
232+
return 1;
233+
}
234+
235+
#endif

0 commit comments

Comments
 (0)