Main Page · Modules · All Classes · Class Hierarchy
MASkitDatabase.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MASkitDatabase.hpp"
23 
24 #include "MAMotionSkit.hpp"
25 #include "MASkit.hpp"
26 
27 #include <MCBinaryData.hpp>
28 #include <MCLog.hpp>
29 #include <MCZipper.hpp>
30 
31 #include <boost/scoped_ptr.hpp>
32 
33 namespace MA
34 {
35 MCThreadLocalData<MASkitDatabase> SkitDatabase(true);
36 }
37 
38 namespace
39 {
40 static std::string SkitDatabaseID = "SkitDatabase";
41 }
42 
43 void MASkitDatabase::AddSkit(MA::SkitSPtr skit)
44 {
45  if (!skit.get())
46  {
47  MC_WARNING("Cannot add a skit. Empty pointer.");
48  return;
49  }
50  if (GetSkit(skit->GetName()).get())
51  {
52  MC_WARNING("Cannot add a skit (%s). An other skit with the same name is already in the database.",
53  skit->GetName().c_str());
54  return;
55  }
56  Skits.push_back(skit);
57 }
58 
59 
60 MA::SkitSPtr MASkitDatabase::GetSkit(const std::string& name)
61 {
62  if (name.empty())
63  {
64  MC_WARNING("Cannot get a noname skit.");
65  return MA::SkitSPtr();
66  }
67  for (auto& skit : Skits)
68  {
69 // MC_LOG("Skit query: %s", Skits[i]->GetName().c_str());
70  if (skit->GetName() == name)
71  {
72  return skit;
73  }
74  }
75  return MA::SkitSPtr();
76 }
77 
78 
79 void MASkitDatabase::MirrorSkit(const std::string& name, const std::string& mirrored_name)
80 {
81  if (name.empty())
82  {
83  MC_WARNING("Cannot mirror a noname skit.");
84  return;
85  }
86  if (mirrored_name.empty())
87  {
88  MC_WARNING("Noname mirrored skit cannot be created.");
89  return;
90  }
91  if (GetSkit(mirrored_name).get())
92  {
93  MC_WARNING("Cannot add a new mirrored skit (%s) because it is already in the database.",
94  mirrored_name.c_str());
95  return;
96  }
97  MA::SkitSPtr Skit(GetSkit(name));
98 
99  if (!Skit.get())
100  {
101  MC_WARNING("Cannot find the skit (%s) to be mirrored.", name.c_str());
102  return;
103  }
104  MA::SkitSPtr NewSkit(Skit->CloneMirrored(mirrored_name));
105 
106  // MASkit::CloneMirrored() already drops a warning thus it is not needed here again
107  if (NewSkit.get())
108  AddSkit(NewSkit);
109 }
110 
111 
112 void MASkitDatabase::RemoveSkit(const std::string& name)
113 {
114  if (name.empty())
115  return;
116 
117  for (auto iter = Skits.begin(); iter != Skits.end(); ++iter)
118  {
119  if ((*iter)->GetName() == name)
120  {
121  Skits.erase(iter);
122  return;
123  }
124  }
125  MC_WARNING("Cannot remove a non-existing skit (%s)", name.c_str());
126 }
127 
128 
130 {
131  MirrorSkit("turn_right", "turn_left");
132  MirrorSkit("lie_exercise1", "lie_exercise1_reverse");
133  MirrorSkit("lie_exercise2", "lie_exercise2_reverse");
134  MirrorSkit("lie_exercise3", "lie_exercise3_reverse");
135  MirrorSkit("stand_fart1", "stand_fart1_reverse");
136  MirrorSkit("stand_fart2", "stand_fart2_reverse");
137 }
138 
139 
140 bool MASkitDatabase::SaveToFile(const std::string& file_name, const MA::BinaryDataSPtrList& skits)
141 {
142  int OverallDataSize = 0;
143 
144  // Verify that the motion data is valid and calculate their overall size
145  for (unsigned int i = 0; i < skits.size(); ++i)
146  {
147  boost::scoped_ptr<MASkit> Skit(MASkit::DecodeAibData(*skits[i]));
148 
149  if (!Skit.get())
150  {
151  return false;
152  }
153  OverallDataSize += skits[i]->GetSize();
154  }
155  int FinalDataSize = SkitDatabaseID.size()+OverallDataSize+skits.size()*4;
156  MC::BinaryDataSPtr FinalData(new MCBinaryData(FinalDataSize));
157 
158  FinalData->AddString(SkitDatabaseID);
159  for (unsigned int i = 0; i < skits.size(); ++i)
160  {
161  MCBinaryData& MotionData = const_cast<MCBinaryData&>(*skits[i]);
162  int OldPosition = MotionData.GetPosition();
163 
164  FinalData->AddInt32(skits[i]->GetSize());
165  MotionData.SetPosition(0);
166  MotionData.WriteData(*FinalData, MotionData.GetSize());
167  MotionData.SetPosition(OldPosition);
168  }
169  MC::BinaryDataSPtr CompressedData(new MCBinaryData);
170 
171  MCZipper::CompressZlib(*FinalData, *CompressedData, MC::FastCompression);
172  return CompressedData->SaveToFile(file_name);
173 }
174 
175 
176 MASkitDatabase* MASkitDatabase::LoadFromFile(const std::string& file_name)
177 {
178  MC::BinaryDataSPtr FileData(new MCBinaryData);
179  MC::BinaryDataSPtr UncompressedData(new MCBinaryData);
180 
181  if (!FileData->LoadFromFile(file_name))
182  {
183  return nullptr;
184  }
185  MCZipper::DecompressZlib(*FileData, *UncompressedData);
186  if (UncompressedData->GetString(SkitDatabaseID.size()) != SkitDatabaseID)
187  {
188  return nullptr;
189  }
190  MASkitDatabase* SkitDatabase = new MASkitDatabase;
191 
192  while (!UncompressedData->IsPositionAtEnd())
193  {
194  int SliceSize = UncompressedData->GetInt32();
195 
196  if (SliceSize < 0 || SliceSize > UncompressedData->GetSize()-UncompressedData->GetPosition())
197  {
198  delete SkitDatabase;
199  return nullptr;
200  }
201  MC::BinaryDataSPtr SkitData(new MCBinaryData(SliceSize));
202 
203  UncompressedData->WriteData(*SkitData, SliceSize);
204  SkitData->ResetPosition();
205  SkitDatabase->AddSkit(MA::SkitSPtr(MASkit::DecodeAibData(*SkitData)));
206  }
207  return SkitDatabase;
208 }
Binary data class.
void AddSkit(MA::SkitSPtr skit)
Add a skit.
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
void RemoveSkit(const std::string &name)
Remove a skit.
static bool SaveToFile(const std::string &file_name, const MA::BinaryDataSPtrList &skits)
Assembly a database file.
bool WriteData(MCBinaryData &target, int capacity=-1)
Write data into a target instance.
void SetPosition(unsigned int position)
Set the cursor position.
MA::SkitSPtr GetSkit(const std::string &name)
Get a skit.
void CreateMirroredSkits()
Create mirrored skits (left and right leg joints are swapped)
Skit database class.
static void DecompressZlib(const MCBinaryData &input_buffer, MCBinaryData &output_buffer)
Decompress data with zlib algorithm.
Definition: MCZipper.cpp:445
static MASkit * DecodeAibData(const MCBinaryData &binary_data)
Load a skit from binary data.
Definition: MASkit.cpp:203
static MASkitDatabase * LoadFromFile(const std::string &file_name)
Load skit database from file.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...
static void CompressZlib(const MCBinaryData &input_buffer, MCBinaryData &output_buffer, MC::CompressionLevelsType compression_level)
Compress data with zlib algorithm.
Definition: MCZipper.cpp:411
void MirrorSkit(const std::string &name, const std::string &mirrored_name)
Mirror a skit.
int GetPosition() const
Get the current position in the binary data.
int GetSize() const
Get binary data size.